3 ms·
Probably not the most difficult but certainly the among the weirder ones I've ever done. Coworker was leading a project that had to get a Qt/QML software to sh
by bostik 13y ago
Probably not the most difficult but certainly the among the weirder ones I've ever done.
Coworker was leading a project that had to get a Qt/QML software to show an accelerated and responsive display in at most 3.5s from power-on. On his request I was pulled in to solve the hardest part of that pipeline.
All the simple solutions had been done already: boot loader timings were down to nothing; the NAND flash driver was optimised for reading with UBIFS tweaks; we loaded kernel modules in sequences of parallel insmods so the wallclock time was kept at minimum; and so on...
A year or two earlier we had discovered an Intel engineer's presentation about optimising Qt binary load times. The two main tricks were to build a completely static binary, and to reorder the binary symbols in the order they were read. Through unofficial channels I found out that Intel used a customised linker to generate their symbol list orders in fully automated fashion. I did not have enough time for that luxury, and as a bonus I had to deal with proprietary 3D drivers and their respective kernel modules. Fully static linking was not an option.
I ended up using OBS in a very weird way. I had three diffrerent Qt builds. One was explicitly compiled for dynamic builds without ANY optimisations, all inlines disabled, and with function call tracer enabled. The other had all the regular optimisations and was built statically. to be used in production. The static Qt was patched just enough to allow loading dynamically built 3D driver modules. This was necessary for the next step...
The software was built against the dynamic, deoptimised Qt. It was then run on the target device and the function call trace log was saved. (GCC's function call tracer only worked with dynamic libraries.) The log was saved and extracted. I then had set of tools; one to extract the order the Qt symbols were accessed. Another to extract the symbols from the Qt libraries. And a third one produced a linker script to force the library symbols to be linked in a static binary in the order they were read.
These tools together produced files for the final Qt build: a static, heavily optimised Qt with the ability to load 3D driver modules at runtime to avoid (L)GPL mousetraps. This Qt static build contained only the symbols that were needed to build the final binary. This way, when building the optimised binary, we knew that there were no unnecessary symbols in the product binary - and with the linker script we had forced them so that the read from the NAND flash could be a single linear sweep.
The reason to do this in three distinct phases was to ensure that the client could reproduce the steps in their own OBS instance. If and when they updated their QML code to use new functionality, they could then regenerate the intermediate files and the final binaries. Once documented and tested, the full cycle took about 10h total, thanks to the need to rebuild the intermediate Qt.
These tricks got the final boot time to about 3.9s. The coworker who had requested my assistance came up with the final trick: patch Qt a bit more to allow loading graphics in pre-processed form, so that they would not need to go through all the intermediate parsing steps. We did a few profiling runs and discovered that processing the PNG files, even when built into the binary as static assets, took nearly 700ms in total to transform them into regular Qt pixbufs.
It wasn't the hardest project I've been in, but it pulled off a lot of low-level magic to get around system and platform limitations. And it was certainly satisfying once the problems were sorted out. :)
- CamperBob2 13y agoInteresting -- was this for a digital camera or something similar? It seems that many developers just use sleep/wake functionality when extremely fast bootup (or the appearance thereof) is necessary. I've got a FLIR infrared camera that runs Windows CE, which takes a lot longer than 3-4 seconds to cold-boot. The camera initially goes to sleep when you power it off, then after a day or so it shuts down entirely to save its batteries. One nice thing they did was to include enough intelligence in the low-level ASIC to drive the display with an unprocessed, uncalibrated live image while the user is waiting for the "real" camera application to come up. Much better than staring at a blank screen for 20-30 seconds.
- bostik 13y agoNo, not a camera. An IVI system. That's all I can say about it for now. (Although I did learn to dislike 3D drivers in that project. With a passion. Can't get contiguous kernel memory? Oh, I'll just wait here and block until I get what I want. What, you wanted to do something ELSE while I probe the hardware and spend 1.15s initialising myself? Tough luck, go sit in a corner and cry.)