Friday, March 25, 2011

Short Story of a Long Struggle - Part 1: the announcement that never came...

Back in September I was writing about some HUGE announcement to come related to KDE on Windows. I got everybody holding their breath, even a bit of speculation going on, but then nothing happened. The announcement never came...


So what happened ? What was that announcement about ? And why didn't it come ?

Well, this is the short story of a long struggle...

Our announcement was going to be about the porting of the KDE stack on Windows CE, including parts of kdelibs and kdepim, as well as all their dependencies: dbus, Akonadi, OpenSSL, SASL...

However, just as we were getting the announcement ready after seeing the first kde-based apps running (the first ever was kde4-config.exe) we started hitting wall after wall...

First, we got hit by the drastic process and memory limits of Windows CE5 (on top of which Windows Mobile is based), which were so tight that  even starting the simplest apps would be problematic. Just to name a few: maximum 32 processes can be running system-wide, and each process has a limit of 32MB of RAM, including loaded DLLs. So first we had to go through a complete overhaul of the build process to try and work around those limitations, for example by switching from DLLs to static libraries. This was so that the unused parts of the libs would be automatically discarded by the linker: bringing 20MB of DLL code for only a few used symbols is hardly a good idea when you're short on RAM. We also had to get Qt to go through a severe diet, by removing every single unused feature we could find, and of course having to go through the KDE code to #ifdef out parts that were relying on these features.

Once we were done, our next wall was the Visual Studio emulator, which is a great tool for testing when you don't have an actual Windows Mobile device, or even for faster debugging. But for some reason, the emulator couldn't handle more than 20 file handles being open or so. We looked for alternatives and it took us some time to work around it too, but as far as I know we never really found the cause for that one.


But then the memory issues hit us again: even with a slimmed Qt and static libraries, our executables were now quite large, and taking most of the allowed 32MB of process memory, which is heap+stack+program image+DLLs from all processes (yes, you read it right, but please don't even ask). This this left only very little heap space for the actual program, and that is not good news when you're running a QML app, with lots of images that have to be stored in heap memory. So we had to find a remedy. And it came from our fellow developer Marcus Brinkmann, from g10code, which was our partner on the project. The idea was very simple, and at the same time completely crazy : write a custom program loader which loads the program in high-memory space instead of the process space. This is based on the fact that Windows CE has a huge portion of its virtual memory space that's unreserved, so it can be allocated e.g. for shared memory segments. By managing to get the program loaded in this area (called hi-mem), all the per-process limits are lifted. This seemed insane but it was our only option at that point, so we gave it a try. And guess what : in less than 3 weeks, Marcus got a a fully functional and working hi-mem program loader: himemce.exe ! There are few things that really impress me in programming, but this was definitely one of them ! If you're interested, the code is available as part of gnupg's wincetools repository and should be usable for any program on WindowsCE, not only KDE.

But the dude didn't leave it here : since we could load the program in the hi-mem space, why not allocate our heap data there as well ? Well, no guts no glory ! So Marcus did it again, and faster than you can say "shallow grave" he brought us his infamous dlmalloc, which is a malloc() replacement that allocates memory blocks in the hi-mem space. The last step was just to integrate that into our program as the underlying malloc() used by the operator new. And even better, by reimplementing qMalloc() we could even get all of Qt's heap allocations to be done into high memory ! Success at last !



So, with our applications now running without hitting the platform limits, you may think this is where the story ends... Happy ever after ? Well, yes, if you're in a Disney movie. But this is the real world, and ponies don't stay pink for long...

4 comments:

  1. Try porting to WinCE 6/7 instead. All of these issues are fixed by WinCE 6/7 (Windows Phone 7 is based on this)

    ReplyDelete
  2. I did got a complete Qt application running on WinCE5, how did I do it? Using jemalloc us my custom malloc I was able to use the all of 128 mb of RAM the device had! :-)

    ReplyDelete
  3. Seeing how complex it all was and taking into account that the usage of windows mobile versions previous to windows phone 7 is declining rapidly I wonder if it was worth it.
    Anyway, great job and I'm sure you've learnt a lot in the process.

    ReplyDelete
  4. @ismail: yep, way to go ;) this is pretty much a must for any app running on ce5, glad to hear you guys managed it as well!
    @sasha & anonymous: yes we've been hearing this sort of things all along, believe me ;)
    But the truth is, the maemo and meego port wouldn't be where they are now if we hadn't gone through the wince port. For all its shortcomings, wince forced us to make kontact a real mobile application, that is an application designed for low cpu/mem/power devices. Porting an app from desktop to mobile is a lot more than just rewriting the UI, it also involves redesigning a lot of the infrastructure to adjust to the platform. We wouldn't have been conscious of many aspects hadn't it been for wince.

    In addition, many other areas benefited from this port: the windows port of course, since we've been using the same emerge build tool as we use for windows. This port brought cross-compiling support to emerge, now allowing us to do x64 builds, for example.
    But even linux benefited from our effort, as we merged our kdelibs modularization improvements upstream, and much more. So I definitely think this was worth it!

    ReplyDelete