RunParallel creates goroutines and distributes benchmark iterations among them. This exposed lock contention that a serial benchmark politely concealed. It is still synthetic: all workers hammering one key may be less realistic than production, so I use representative key distributions too.
The same upgrade broke a test that compared map traversal output to a fixed string. Go 1.3 randomizes iteration order for small maps, making an assumption that was always invalid fail more reliably.
Sorting is correct when output order is part of the result. For equality, I compare contents instead of rendering iteration order.
Random order is not cryptographic randomness, nor should a program depend on getting a different order every pass. It is an implementation defense against accidental ordering assumptions, not a shuffling API.
I approve of the randomization. A runtime that accidentally rewards a bad assumption lets the assumption become an API. My test was not flaky; it was finally honest.
Even though I’ve been playing Kerbal Space Program for over a year, I have only barely explored the outer kerbolar system. I have been around Jool before and I have even landed on Laythe but never managed to make a round trip until this week.
Traveling all the way to Jool’s moon Laythe and back is not easy[citation needed]. It’s not so much getting there—although that’s not trivial, either—but we want to land on Laythe and we want to get back to orbit later: that takes a lot of fuel.
This is my adventure.
Mission Overview
The Kerbal Air and Space Agency (KASA) will be sending two separate missions: the Laythe Recovery System (LARS) and the Laythe Orbital Landing System (LOLS). The LARS stack is controlled by an automated probe and its function is to carry fuel for the travel back.
Although huge, it is only as heavy as it needs to be to deliver fuel, lacking scientific instrumentation and communication systems other than the Clamp-O-Tron’s acquisition signal.
The second stack is LOLS, which will carry a 3-kerbal crew, the lander itself, and all the scientific instruments: a gravioli detector, a termometer, a barometer, and a Mystery Goo™.
The two stacks will launch a couple of days between them and will meet in orbit around Jool over two years later. LOLS will then rendezvous with LARS, dock, and transfer any remaining fuel from its tanks and then drop its large tank before the LARS will then make the Hoffman transfer to Laythe1.
LARS Launch and Trans-joolian Insertion Burn
The first of the two missions to launch was LARS, the rationale being that if something were to go wrong later that prevented the LOLS launch, LARS could wait in Jool orbit for the several years until a new interplanetary window opened to allow LOLS—or its successor—to go rendezvous with it. It would be harder to keep a Kerbal crew waiting there2.
Also, to minimze the risks, LARS was launched as soon as the window opened, allowing for more time to deal with any issues with LOLS later. This resulted in a night launch.
Showing that LARS was not too heavy, it quickly started accelerating towards terminal velocity and we lower the thrust to about 80% so we don’t waste fuel fighting drag.
At 7300m we start the roll program to begin gaining horizontal speed. A little later, just passing the 10,000m mark our two first boosters run dry and we have a beautiful separation.
At its parking altitude of 240Km, the probe circularizes its orbit and, as Robert Heinlein would have said it, we are halfway to anywhere3.
About 2 hours after settling in its parking orbit, LARS is GO for TJI. This burn adds the 1,907m/s delta-V needed for LARS to reach Jool.
After the burn is done, LARS is on its way. Time to remember to extend our four Gigantor solar panels to ensure the probe will have power in its journey4.
With LARS now on the way, the KSP staff turns its attention to their next mission: LOLS.
LOLS Launch and Trans-joolian Insertion Burn
LOLS presents its own set of challenges. It is considerably heavier than LARS because not only it carries a similar amount of fuel—which it will spend much more quickly due to the extra mass—but it also adds the crew, large capsule, and scientific instrumentation.
With the greater weight, the engines struggle to lift off the launch pad. It takes almost 20 seconds to clear the flag pole by the pad.
It never comes close to terminal velocity while in the atmosphere and the throttle remains at 100% all the way. It begins roll program at 7300m and has barely accelerated past the 200m/s mark at this point.
After another beautiful separation, the speed is mounting a bit faster now…
… but it still takes a while. As well, although LARS managed to reach orbit on its second stage alone–albeit running on fumes at the end—, LOLS had to rely on the third stage to reach orbit, spending half its fuel tank.
About 90 minutes after reaching the parking orbit, LOLS is GO for TJI. Delta-V needed is 1,904m/s.
Over a million kilometers behind LARS, LOLS is now on its way for the long, nearly-two-year-long journey to Jool.
Deep space Transfer
During the long transfer period spend after escaping Kerbin’s sphere of influence and before the encouter with Jool, the crew does some science.
Tonmen Kerman goes EVA for a while and reports back to Kerbin. They also do a crew report and use the gravioli detector for some extra science production.
The original plan was to have LARS arriving first and waiting for LOLS to arrive. That would make sense as LARS is an automated probe while LOLS is carrying actual kerbals. That is why mission control5 naïvely launched LARS first. As it turns out, it was a mistake.
As you can see in this picture, LARS is indeed ahead of LOLS. However, due to their positions in relation to Jool itself, LOLS ends up getting caught by the Jool sphere of influence before LARS. This caught mission control by surprise and almost ended the mission as all its attention was on the LARS approach and only by sheer dumb luck they noticed LOLS encountering Jool SOI.
In retrospect, this makes perfect sense. In the 1-2 days following the launch of LARS, Kerbin and Jool were moving in relation with each other. Kerbin, having a much lower orbit than Jool’s, was moving faster and since it was “behind” Jool, this meant both planets were actually getting closer to each other so LOLS had a slightly shorter trip than LARS. That’s orbital mechanics for you.
LOLS Aerobreaking and Joolian Orbit Insertion Burn
One year, 270 days into the mission, LOLS, already deep inside the joolian SOI, maneuvered to adjust its periapsis to 110Km above Jool. Jool’s atmosphere begins at around 138Km of its sea level, which is not that much considering how big the planet is. But that atmosphere is very dense, which is good for aerobreaking, saving us some precious fuel.
Two days later, LOLS reaches Jool…
… and falls 30Km into its dense atmosphere for some heartstopping aerobreaking.
Mission control found 105Km to be a great aerobreaking altitude as LOLS re-emerged from the atmosphere with an apoapsis of a tad over 500Km, which required very little delta-V during the Joolian Orbit Insertion burn to reach the desired parking orbit of 400Km. The crew adjusted their apoapsis and periapsis and waited for the LARS to arrive. This was the early hours of 1y 273d MET6.
LARS Aerobreaking and Joolian Orbit Insertion Burn
Twenty seven days after the arrival of LOLS in Jool, LARS enters Jool’s SOI. LARS will try for an approach with a periapsis a little lower: 105Km. The 5Km difference doesn’t sound much but considering the density of Jool’s atmosphere, it makes a difference.
Despite mission control’s best efforts to point it retrograde, LARS insisted in going nose first.
LARS leaves the atmosphere with a apoapsis of a little under 400Km, again leaving little delta-V for the JOI burn. It parks at 280Km. This is 1y 386d MET, meaning the intrepid kerbal crew waited in orbit for 113 days for LARS, even though their total mission time so far was a little under 2 days shorter than LARS’.
Rendezvous and Docking
As soon as LARS settled in its parking orbit, the LOLS crew starts working on the rendezvous maneuver. A good encounter happens after 5 orbits around Jool.
Once docked, the crew transfers all the fuel remaining on the LOLS main tank to LARS and ejects it. From now on, LARS will be doing the heavy lifting of the Trans-laythean Injection.
Trans-laythean Injection and Laythean Orbit Injection
(I mentioned early on that rendezvous in Jool orbit proved to be a mistake. The why might become more clear from this picture.)
The two small extra boosters added to LOLS made it a bit too much for the Clamp-O-Tron docking port to hold. When LARS ignited its engine for TLI, the centre of mass shifted slightly but enough to make LOLS wobble and put on too much stress on the docking port, which then broke. (Thankfully I had quicksaved just before the burn and was able to recover.)
The crew slowly pushes on the throttle to ease on the clamp-o-tron stress. Same thing during LOI: easy on the throttle. The crew and mission control also agreed to skip the aerobreaking, the rationale being that Laythe’s atmosphere is low (55Km) and not very dense so it would probably not help them all that much and they did not want to put on more stress on the docking port.
Undocking LOLS and Landing
At this point, the crew transfers fuel from the LARS main tank to the three LOLS tanks and undocked. Time to land.
Laythe is touch to land for two basic reasons:
It’s almost entirely made of oceans, with some relatively small islands and continents; and also
The islands and continents are rough! Lots of mountains and steep slopes.
The crew ultimately picked the continent that looks sort of like a large ‘C’ with an internal sea.
(It took me a few tries and one big scare as just before landing I noticed a deep valley just ahead.)
LMP Donbro Kerman uses the retro rockets plus the parachutes to slow the LOLS down and slowly descend.
He also has to rotate LOLS around to make sure it lands in a way to prevent it from tumbling over the slope.
It all ends well though, as Commander Roley Kerman steps out of LOLS and steps on Laythe.
Laythe Base
The crew has to remain on the surface until the next interplanetary window before they could go back to Kerbin, which means: time for some science! With some gravioli detection, temperature and barometric measurements, EVA reports, crew reports, Mystery Goo™ observation, and some surface samples, the LOLS crew gets well over a thousand science points.
And they had some fun too, like this little night rave or whatever. This is Donbro standing by the lander legs while Tomner jumps by the flag.
Commander Roley was asleep and missed the shenanigans. Probably for the best.
Takeoff and rendezvous
After a couple of years on Laythe, the crew was eager to go back home.
LOLS rendezvous with LARS, which patiently waited all these years in orbit.
The crew now transfers the remaining fuel from the LOLS tank to LARS’ and jettisons it. Time to go home.
The jorney home
The jorney back is largely uneventful, starting with the transfer from Laythe back to Jool. Now that they got rid of the LOLS tanks, the Clamp-O-Tron docking port is more than capable of holding the capsule in place.
Back in orbit around Jool, LARS is GO for Trans-Kerbal Injection.
And the long journey back to Kerbin is now underway.
Two years later, the crew maneuvers to reach Kerbin with a periapsis of 30Km for some heavy aerobreaking.
They reemerge from Kerbal atmosphere with an apoapsis of almost 2,000Km and running of fumes. The remaining fuel is then used to lower the apoapsis a little bit without changing the periapsis too much. This made sure that on the second periapsis pass, the stack will not make it out of the atmosphere again.
At this point, mission control tries for a bonus mission objective. They plan to land both the LOLS capsule and the LARS rockets at the same time and try to recover the LARS hardware costs. After they stop burning in the reentry, the LOLS capsule undocks from LARS and mission control constantly switch between the two to try and land both.
Unfortunately, saving the LARS was a failure. As soon as the parachutes opened, LARS disintegrated, leaving only the RCS tank and docking port to slowly land.
The LOLS capsule on the other hand had a beautiful descent.
After LOLS splashed down, the capsule, its science payload, and its crew were successfuly recovered. Mission accomplished!
The remaining LARS parts were found to not be recoverable.
A few closing remarks
I was pretty pleased to have completed my longest mission yet. Still, a few things I would have changed.
I wasted fuel by not aerobreaking in Laythe. Also, I am sure there is an optimal altitude that I could have reached Jool for a better aerobreaking. I did try several but going even a bit under 105Km seemed to be too much as the ship never came back out of the atmosphere. A little over 110Km and the apoapsis would end up in the millions of kilometers.
Another thing is that I made the hop in Jool orbit between Kerbin and Laythe. I am not sure it is possible but I think I will try in the future to go directly to Laythe. It must be terribly difficult but a scenario would be to arrive in such an angle that you could aerobreak in Jool and come out with a path leading to Laythe directly, hopefully with some extra aerobreaking. This would be optimal but would require a lot of precision. I don’t think I could make it but it sure sounds like it would be fun.
I should also have scheduled the LOLS-LARS rendezvous to happen in orbit around Laythe instead of Jool to avoid the wobbly lander problem. The LOLS was low on fuel by that time though, so I am not really sure I could have pulled it off anyway.
And I could have taken at least one more Mystery Goo™ as I could have observed it in orbit aroud Laythe for some extra points.
And finally, I love this game so much. You learn more every time you play it. This whole thing, including designing both stacks and doing some testing, was done over the course of a few days, mostly last weekend with the return from Laythe to Jool and then Kerbin done over a couple of nights this week.
I thank Squad for this great game.
May your solar panels be always unobstructed.
UPDATE: this whole story was created way before KSP 1.0 came out. The aerobreaking maneuvers here would not have worked due to the lack of heat shields. As well, a scientist kerbal in the crew would solve my issue above with only taking a single Mystery Goo™ as kerbal scientists can reset experiments in flight.
That would turn out to be a mistake, as we’ll see.↩
Not really, actually, as Kerbals don’t seem to care…↩
Heinlein’s actual quote was “Once you get to earth orbit, you’re halfway to anywhere in the solar system.” I suppose it can be used for Kerbin and the kerbolar system.↩
You learn that the hard way in KSP. How many a time I have arrived somewhere after warping time just to find my ship completely dead because there was no electrical power left.↩
I used Go 1.3’s new sync.Pool to reuse temporary buffers in an HTTP formatter. Then I almost used it to cache parsed templates. The first idea reduced garbage; the second would have randomly forgotten application data.
A pool holds temporary values that may be removed at any time. Garbage collection is explicitly allowed to clear it. That makes it suitable for amortizing allocation of scratch objects, not for storing anything whose presence affects correctness.
The copy before Put is essential. b.Bytes() aliases the buffer’s storage. Returning that slice and putting the buffer back would allow another goroutine to overwrite the caller’s result. Pool safety does not transfer ownership safety to pooled objects.
The pool synchronizes Get and Put, but an object obtained from it belongs to the caller until returned. Two goroutines must not use the same buffer concurrently. Go 1.3’s bytes.Buffer does not expose its capacity, so I use the rendered length as a simple retention policy: a response that grows a buffer past 64 KiB does not return that buffer to the pool. It is only a proxy for capacity, but it keeps a freshly oversized allocation out of the pool.
In a benchmark of the formatter, pooling reduced allocation volume:
The output copy accounts for necessary ownership. If the function wrote directly to an io.Writer, even that copy could disappear, probably a better API than ever more pooling.
New should return the expected type consistently. A pool may omit New, in which case Get can return nil and every caller must handle that. I define it when all callers need the same scratch type; this keeps allocation policy together without pretending values are permanent.
Copying a sync.Pool after first use is invalid because its synchronization state and local storage are not value-like application data. I keep pools as package variables or pointer-owned fields initialized once.
I would not add sync.Pool without allocation profiles and a benchmark. It obscures object lifetime and may provide little benefit when allocations are already short and cheap. A cache promises retrieval; a pool merely offers to rummage in a box the collector is free to empty.
About an year ago, I started a new project in a stealth startup. Aside from the fact that it would provide currency that could then be exchanged for goods and services, including food for me and my family, one of the biggest reasons I took the job was that I was going to get to learn a lot of new things.
Now, over a year later I can say that learn I did. And I caught myself thinking of what I wish I knew back in the beginning. The following list is probably not exaustive but it’s a good example of what I’ve learned. These are mostly things I’ve dealt with on rewrites, redesigns, or are things that I still struggle with.
JavaScript is magical and that’s not good
I already had a general idea of the issues with JavaScript, but I really failed to grasp how magical JavaScript is. And when I say magical, I don’t mean the good kind that conjures fluffy rabbits inside hats. I mean evil dark magic that would make Voldermort cry. I mean magic in the sense of a language that never seems to behave just the way you think it should.
I wish I knew back then how much work I would need to spend to do what seemed at first to be basic, simple stuff. I often caught myself fighting JavaScript instead of working with it.
AngularJS is awesome but the web works on jQuery
I think AngularJS is fantastic. Really I do. I am not at all sorry for having picked it for the project. I think it’s well-designed and logical and yes, it is magical sometimes, but often in a good way.
But…
I wish I knew back then how much work I would have to do making AngularJS and jQuery work together, and you have to make them work together because honestly, unless you want to reinvent the wheel for every little thing, you will end up using jQuery components. We will revisit that later.
So yeah, AngularJS is great but for it to work properly, you have to do things the Angular way and that means turning a lot of jQuery components into AngularJS directives. Once you get the hang of it, it gets much easier and faster but there’s a bit of a learning curve there.
asynchronously have You think undefined
You have to think asynchronously to work with JavaScript. For a while, it was painful and it surely added to my perception of JavaScript being magical. JavaScript is entirely asynchronous and works like a turn-based game. This can be annoying at first and I caught myself working around this in all kinds of wrong ways. I wish I knew back then what I know now so I’d embrace the async’ness from the get-go. Things would be so much easier.
Large single-page web applications rock but…
Picking AngularJS as my framework of choice, I designed the web client for the project to be almost purely implemented inside the browser in JavaScript as a single-page app. This has some very good consequences, chief among them responsiveness. The application feels fast. Sure it has to download a lot of JavaScript up front, but (1) this is not nearly as bad as I expected it to be and (2) with caching this is done once and that’s it. Switching from a “page” to the other is essentially instantaneous as it’s all pre-loaded AJAX parts of the page. The server actually has to do very little.
But now, if I could start all over again, I would not do it like one big single-page app. It’s just too much JavaScript code and I’ve already established how I feel about that. I never have the feel that things are stable, even though there are integration tests passing all the time. I can’t explain it but it all feels like a big house of cards, like it’s all going to come tumbling down all of a sudden. I simply don’t trust the code. I would much rather use JavaScript sparingly, to do some things but surely not all. I have been fixing this slowly by isolating some parts of the application as separate, but to do it for everything would require a rewrite that I don’t have the time for right now.
Trust the Go standard lib
As an alternative title, “don’t go too fancy with Go.” It’s not that I didn’t trust it, but I sure did try things that honestly didn’t make sense. I am looking right at you, Martini, I had to do a lot of work to get rid of you.
As it turns out, the standard library is really good. And for the things that are not in the standard lib, there are packages that are really well done and work with the standard lib, not against it. I love you, Gorilla Toolkit.
Never assume jQuery components will do what you need
The current state of JavaScript is such that there is literally—in the figurative sense—an infinite number of components out there ready for you to use. As far as I can tell, anything I could ever possibly conceive of has already done and hosted on Github. There are time pickers, calendars, and even a business hours widget display ready for you.
And yet.
I am yet to find one single component that is flexible enough to work for my needs without extensive modifications. And it’s not like I have especially unique needs. I am talking about things that are to the best of my knowledge pretty basic. But no, they never do that one tiny thing you need them to and I spend a lot of time implementing features I need.
Bootstrap responsiveness
For a long time I misunderstood how Bootstrap deals with responsive design. Trusting Bootstrap’s system is a must. It works very well. I wish I understood it better back then. It would have saved me a lot of time. And related:
Don’t use an existing Bootstrap theme
It’s just not worth it. Back then, we didn’t have a designer and we wanted to have our minimum viable product as quickly as possible so we went after something ready. We chose a premium theme that is very popular. It was good looking and seemed really nice. Boy do I wish I had a time machine now.
We are now stuck with it. Switching to something else is something we will have to do eventually and let me tell you: it will be painful. These themes change everything and not in a way that we could simply switch themes painlessly. It permeates everything.
Think of touchscreens from the beginning
Oh boy. You do a lot of nice stuff and then one day you try it on a tablet and nothing works just as your co-founder tells you that your first customer will use the app exclusively on tablets. Then you start panicking and sobbing and crying and running for help. You then find out about the hack that is jQueryUI Touch Punch and although it fixes some of the problems it creates new ones and then there’s jQuery Mobile which is OMG fantastic except lo and behold it doesn’t play well together with AngularJS. And then you find some projects on Github trying to get jQuery Mobile to work alongside with AngularJS but they’re no longer maintained and won’t really work that well and…
Well, it would be best to think about touch support from the get go.
Stop worrying about the size of your JavaScript
Or actually, do worry, but for the right reasons. One of the things I learned is that the web is full of outdated and/or otherwise uninformed advice.
Stop laughing.
Yes, it’s obvious, but still. With little experience with web frontend programming, I used to worry about the size of my JavaScript code. And the web doesn’t really help. Search a bit and you will find people telling you how horrendous it would be to download 100Kb of JavaScript and how the only way to save your customers is to access files from popular CDNs.
It turns out that’s kind of like cargo cult programming. It’s just a bunch of people repeating something they heard somewhere. Things change. We measured them.
Concatenating and minifying our files and serving them gzip’d and with aggressive caching is actually faster. Even concatenation is about to become irrelevant now that SPDY is becoming more common (IE11 now supports SPDY3 and the upcoming versions of Safari for OSX and iOS will as well.)
The first access to our app downloads almost 1MB of JavaScript code and CSS files. It sounds horrible but it’s really fast, even on bad 3G with with defer and async. Speaking of which.
Most of the advice repeated as a mantra on the web is from before browser support for <script defer> and <script async> was widespread.
I think that’s about it. Now all I need is a time machine.
One of our larger binaries spent enough time linking that I could switch windows, forget why, and begin an unrelated task. Go 1.3’s linker refactor made that interruption noticeably shorter.
The old linker represented symbols and their data using structures that encouraged many small allocations and expensive traversals. The 1.3 work reorganized that machinery around more compact symbol data and a cleaner division of the linking stages. The user-facing command did not change:
$ go build ./cmd/server
The wait did. On one clean build of our program I saw roughly:
Go 1.2.2 real 4.8s
Go 1.3 real 3.1s
This is not a controlled toolchain benchmark. Installed package archives, the filesystem, machine load, and exact source all affect it. Repeating alternating builds from the same installed state still showed enough difference that it was not merely optimism generated by a new version number.
Linking a Go program is substantial work. The linker reads object data for the program and imported packages, resolves symbol references, applies relocations, lays out executable sections, emits metadata used by reflection and the runtime, and writes the target executable. It also removes unreachable code and data. A statically linked Go binary may contain a great deal of runtime and type information, so representation overhead inside the linker matters.
The refactor is interesting because it improves a tool by making its internal model less elaborate. No language feature was needed. Existing builds became faster and used less memory because the implementation stopped turning every byte and symbol into quite so much bookkeeping.
I still avoid reading too much into final binary size. Importing a package can pull in initialization and reachable symbols, reflection can retain type metadata, and debug information contributes too. A smaller linker heap is not the same thing as a smaller output file.
Cross-compilation makes architecture-specific tool names visible in this toolchain. The compiler and linker remain separate programs selected for the target architecture, even though go build normally hides the sequence. When investigating a failure I use go build -x to print invoked commands rather than reconstructing them from folklore.
That output also shows whether the build uses installed archives from GOROOT/pkg and GOPATH/pkg or recompiles packages. Without it, I had occasionally blamed the linker for time actually spent rebuilding a dependency after a build-tag change.
Benchmark builds with and without the relevant installed archives separately. Archives installed for the standard library under GOROOT/pkg and for workspace packages under GOPATH/pkg can hide compilation work; release builders often expose linker time more clearly. Go 1.3 improved both my build and my attention span, though only one claim has numbers behind it.