A248 / LibertyBans

The be-all, end-all of discipline.
https://ci.hahota.net:8443/job/LibertyBans/
GNU Affero General Public License v3.0
169 stars 41 forks source link

Reduce resource usage running dockerized integration tests #226

Open A248 opened 1 year ago

A248 commented 1 year ago

As Simon wrote on Discord:

I'm wondering, if it would be possible to reduce the LibertyBans builds memory usage. To my testing, when running the build without docker, it uses about ~2GBs of memory, which seems fine. However with docker enabled, for me it exceeds 8GBs, and potentially more, which seems a bit more than what it should use.

I understand that running 5+ databases at once can use a bit of memory, especially that the build process imports data into them, and then interates over later, but does that actually need this much? 🤔

Also, I wonder, would it be possible to create and then sequentially start/stop these containers during testing? This would greatly reduce memory usage, I think.

A248 commented 1 year ago

For sure, the dockerized databases are the greatest source of memory usage. However, there are a couple challenges.

The apparent solution would be to run multiple executions of maven-surefire, the testing plugin, with one execution one for each database, so that we could start and stop the containers before and after. The docker containers are created by docker-maven-plugin in the pre-integration-test phase, which runs before the tests; afterward, docker-maven-plugin cleans up the docker containers in post-integration-test. The integration tests therefore take place between runs of the docker plugin. Unfortunately, Maven has a limited number of phases, so we can't create pre-integration-test-mariadb and post-integration-test-mariadb while running our tests in integration-test-mariadb, for example.

An alternative would be to create the docker containers programmatically, inside the test runner JVM. However, I don't know of a way to instruct JUnit to group test runs according to database. Even if I could tell JUnit to do this, there remains an additional hurdle to programmatic creation. The library for programmatic docker usage, testcontainers-java, is riddled with split packages and other nonsense. There is no way I am using a library whose maintainers carry out such practices. Actually, we could create our own testcontainers; it might not be very difficult, although I'd have to take look at existing approaches.

KoxSosen commented 1 year ago

Interesting, thank you for your explanation. Regarding maven-surefire, the only solution that I see is switching to gradle, however that's an astronomical task as you said in #68 because of reasons mentioned in the issue, so this might not be the correct approach. For the long term, I'm absolutely for switching to gradle, but I see the absurd amount of work required to convert the current system that can be invested in working on other parts of the codebase.

You suggested creating a testcontainers like framework for LibertyBans as another solution, after somehow working out how to instruct JUnit to group tests. Do note, that after a little research in the space, I wasn't able to find anything that is maintained, and is like testcontainers-java, so with that resource you would be filling a hole in the ecosystem, and might end with a library that would be used by others as well; Maintaining that will be lots of work as well.

In all of this, I wonder, is there an alternative solution to using dockerized databases for testing? I'm afraid we'll have to choose from one the previously mentioned solutions. If we have to, I'm voting for the gradle approach, as for long term it brings many other benefits. Also, I wonder, what do others think about this? If you are reading this issue, please consider writing your opinion, as it's much appreciated.