vector-of-bool / cmrc

A Resource Compiler in a Single CMake Script
MIT License
672 stars 74 forks source link

Increased performance significantly using incbin library #21

Open themarpe opened 4 years ago

themarpe commented 4 years ago

Performance and memory usage improvement

Hi! Big fan of CMakeRC library. Lately I've been working with it a lot and came up with an idea to use the incbin assembly directive to include binary data without the need to create the large character array in the intermediate source file.

I've used the following library: https://github.com/graphitemaster/incbin Which is also license wise compatible to integrate it into this project. This adds support for many compilers with exception of MSVC (See: https://github.com/graphitemaster/incbin#portability) Their solution for MSVC is, to generate intermediate character array files for that case - which this library already does by default :)

I've added a try_compile test which tries to use the incbin library and it falls back to "compatibility mode" if it fails to do so successfully.

Please comment on any changes that would be required to improve this feature.

Performance Increase:

Running improved library with a compiler which supports incbin assembly directive yields enormous performance boost.

Running tests

Machine: i7-4700MQ, GCC 8.4.0, Ubuntu 18.04

Compatibility mode enabled (performance without this feature)

cmake .. -DCMRC_COMPATIBILITY_MODE=ON
time cmake --build . --parallel

Result: 9.675s <- Before

Compatibility off (by default)

cmake .. 
time cmake --build . --parallel

Result: 3.080s <- After

Memory usage:

On Raspberry Pi 3, I had issues using this library with ~5MB files, as the device ran out of available memory. With the above feature, it compiled successfully without any issues.

Running the included tests again with improved library:

/usr/bin/time -v cmake --build . --parallel

Memory usage Before: 540MB After: 86MB

vector-of-bool commented 4 years ago

Sorry for the slow response. I've been on a break for a while.

I didn't know about incbin, but that's pretty cool! I didn't know most compilers/assemblers were able to do this.

If I pull it in, I'll want to do some cleanup since we don't need all of Incbin's functionality (e.g. CMakeRC is, for better or worse, C++-only, so we can remove some of the C/C++ toggles).

I also have been wanting to set up some proper CI for this project, but haven't had the time to get it done.

Also: Have you verified that at least the few tests pass on the common compilers?

themarpe commented 4 years ago

Okay I'll clean up the incbin library in the upcoming days.

I've ran the tests on MinGW (Windows) and GCC on Linux. Otherwise I've successfully compiled a project using this changes with Clang as well.

Regarding CI, I think that you only have to register your project to Travis CI or some other provider, and I can try writing some .yml files for it. (Which will then be ran when I do a pull request)

nanosonde commented 4 years ago

@themarpe Github Actions would also be possible. https://github.com/vector-of-bool/cmrc/actions

themarpe commented 4 years ago

@nanosonde thanks for the suggestion. I've played with Github Actions over the weekend and I must say I quite like them. Will try to find some time and write a matrix to build on Linux, Windows and macOS.

@vector-of-bool regarding modifying incbin library - as the changes would be minimal, maybe we should stick with having an exact content of a commit to be able to easily update to a new commit in case incbin gets an update? Apart from that should anything else be cleaned up?

Has anyone played with MSVC suites Resource Compiler? Maybe we can close the gap and use this tool if it is available?

tambry commented 3 years ago

I tried to use this, but got consistent segfaults. The current master or the compatibility mode worked fine. I used a full LLVM 13 (master) toolchain (clang, libc++, compiler-rt). Don't have a repro, just a FYI. 🙂

themarpe commented 3 years ago

@tambry thanks for the heads up. As of now I've been using this up to clang-11 on Ubuntu 20.04. Hopefully nothing changed on latest LLVM.

Could you try creating an minimum example of failure? Or at least describe your setup? Do tests pass with your current compiler?

tambry commented 3 years ago

@themarpe Investigated and I'm no longer able to reproduce. Was probably caused by a dirty build directory.

From the few runs I did with this vs master the result seemed to be slightly longer build times. My use case has very few (10) small (few hundred bytes) files.
Have you measured the performance yourself in such cases?

themarpe commented 3 years ago

@tambry I have not. Not sure why the build time would increase as its still 1 step less, but the overall generate+compile might just be faster as compiling/linking? the incbin directive.

If you find a reasonable cutoff a threshold can be made.