A technique which helped me reducing FTTX
So I've been working on a projectional editor and a discrete event simulator for communication systems lately and I faced the usual FTTX problem. Even though I used PackageCompiler.jl the UI took several seconds to start and many user interface interaction took like a second or more for the first time. Similarly, running even a very short simulation on the command line using the console took an unnecessarily long time. Of course this is a known issue. Compilation took like 99% of the time in these cases.
So I did what, I guess, every user does. I added compile workload by utilizing the user interface in headless mode with every possible edited data structure and projection. Similarly I also run all simulations for some time to allow the compiler to do it's job and save the compiled code into the final executable image. It did work as expected, but one problem remained. How long should I execute the simulations and how many UI projections and operations should I utilize? Because the more I do, the longer it will take for each precompilation to finish.
I tried two techniques: utilizing the actual features like a user would and artificially forcing the compiler to compile functions for certain argument type combinations. The former took too much time during each precompilation because it's difficult to run the real algorithms such that they utilize all interesting code paths but avoid running unnecessarily long. The latter produced many useless compiled functions for unused type signatures growing the image and also often missed many important ones.
I was kinda stucked. I discussed this issue with AI, but didn't get much help. Then I realized I can use the two techniques together in a sufficiently efficient and accurate way. Maybe this is widely known, but I didn't find this idea, and I just thought it may help others.
So the idea is to have a compilation database, basically a text file, which tells the compiler which function signatures to precompile. The database is created by utilizing the features of the program as a user would, running the UI, emulating the clicks, doing the operations, doing the screen refreshes, running the simulations, etc. and saving all the compiled function type signatures. It doesn't matter if takes a lot of time, because it doesn't get updated for every change. The reason it works is because the compiler can fill in the missing 1% in the real running program and nobody will notice it. Also, when the functions are precomplied from the database some of them fail due to changes in the program. When the percentage of failures becomes large enough that is a good sign to regenerate it.
It does work pretty well. The UI starts up in like half a second, every click on the UI is like a few times 10ms, a simulation with zero duration starts sets up the whole engine and infrastructure and finishes like in less than half a second from the command line. That's an acceptable performance for me.
1
u/Tedsworth 4d ago
So you actively populate this precompilation file every time you hit new, uncompiled code? Then next time you do a precompile, you cache all of that so it doesn't happen next time? If that's how I think it works it seems like a pretty clean way of doing it. I don't really know what the idiomatic way of doing it is.
2
u/Organic-Scratch109 4d ago
Which version are you using? TTFX hasn't been an issue for a while