Poudriere and hyperthreading

I'm currently in the middle of a bulk build waiting for devel/cmake-core to complete and wondering whether It's a mistake to have hyperthreading. I suspect without that a single package on which other builds are waiting might go twice as fast. Hyperthreading might be great for everyday use but for compiling, I wonder whether it's slowing things down as dependencies mean there's a limit to what can be done in parallel and it might be better to have more speed on fewer cores.

What do people think?
 
Using hyperthreading will absolutely speed things up for most tasks, definitely for C compilation.

As long as the increased number of parallel processes doesn't cause you to run out of RAM.
 
I wonder whether it's slowing things down as dependencies mean there's a limit to what can be done in parallel and it might be better to have more speed on fewer cores.
Play around with PARALLEL_JOBS, ALLOW_MAKE_JOBS/ALLOW_MAKE_JOBS_PACKAGES and USE_TMPFS. MUTUALLY_EXCLUSIVE_BUILD_PACKAGES can also be helpful, building 3 different versions of LLVM, a GCC and rust simultaneously is probably slower than building them one at time.

Having fewer concurrent jobs running will give the running jobs more room to use more cores for their own build. If you have plenty of RAM push more into tmpfs(4), RAM is usually faster than disk I/O. Find a good "sweet spot" to get the most bang for your buck.
 
The 'PARALELL_JOBS', 'ALLOW_MAKE_JOBS' and the 'ALLOW_MAKE_JOBS_PACKAGES' options for poudriere.conf might be what you are looking for.
That being said, if the actual build is run with a single or multiple threads is largely dictated by the port and the build chain it starts. Python/wheel or rust/cargo based builds are notoriously single-threaded and hence often a PITA holding up bulk buildjobs...
 
I'm currently in the middle of a bulk build waiting for devel/cmake-core to complete and wondering whether It's a mistake to have hyperthreading. I suspect without that a single package on which other builds are waiting might go twice as fast. Hyperthreading might be great for everyday use but for compiling, I wonder whether it's slowing things down as dependencies mean there's a limit to what can be done in parallel and it might be better to have more speed on fewer cores.

What do people think?
Well, I'd suggest being careful with Makefile knobs. Sometimes, enabling a knob that is not on by default is OK, and sometimes, it turns out to be a bad idea because the port would not compile, and you'll get compiler errors. I've been there with devel/electron43. It does NOT have LTO on by default. I turned LTO on - only to discover that the hours-long compilation fails because of a header file. But when I reverted back to defaults and turned LTO off - the compilation finished, and I had my port compiled and installed properly.

This is really a case-by-case thing. I'd frankly be more worried about accidentally specifying circular dependencies, those can be time-consuming to track down and break.
 
The 'PARALELL_JOBS', 'ALLOW_MAKE_JOBS' and the 'ALLOW_MAKE_JOBS_PACKAGES' options for poudriere.conf might be what you are looking for.
That being said, if the actual build is run with a single or multiple threads is largely dictated by the port and the build chain it starts. Python/wheel or rust/cargo based builds are notoriously single-threaded and hence often a PITA holding up bulk buildjobs...
Ports using cargo are not single-threaded, the linking process is however by default because it reduces binary sizes quite a bit (and in most cases also improves performance).
You can globally disable it however some upstream ports will still enforce it.
 
I'm currently in the middle of a bulk build waiting for devel/cmake-core to complete and wondering whether It's a mistake to have hyperthreading. I suspect without that a single package on which other builds are waiting might go twice as fast. Hyperthreading might be great for everyday use but for compiling, I wonder whether it's slowing things down as dependencies mean there's a limit to what can be done in parallel and it might be better to have more speed on fewer cores.

What do people think?
Disclaimer: This broadly speaking but you get the idea.

How the port actually builds

For example:
* Ports utilizing GNU Autotools (and/or gmake) are in general notoriously slow/processing heavy and have very limited multithreaded. (We have a lot of legacy / old ones in tree)
The ./configure process is always single-threaded and slow, (g)make is relatively smart but do have some limitations when it comes to multiple subdirs however it works pretty good in general.
* CMake and Meson based ports are in general much faster, both during "configure" stage and much better at utilizing cores during builds especially on systems with many slow cores.
This is one of many reason why I have my little overlay repo :-)
* Rust ports are multi-threaded by default, however linking process is single threaded (for performance / size reasons) but can be very compute intensive and memory hungry

I would go out as far as and say that you gain more by allowing more jobs ("threads") per port rather than building more ports in parallel with fewer jobs.
This is a tradeoff and you likely will run out of RAM sooner than CPU power.

On a Ryzen 7900 the following is a pretty good balance in general,
Code:
PARALLEL_JOBS=6
MAKE_JOBS_NUMBER_LIMIT=8

This leaves you with up to 6 ports being built in parallel and each using up to 8 "threads" which is pretty much a sweet-spot with 128Gb RAM and tmpfs despite having only 24 "cores".
Poudriere cannot take into account in scheduling if a ports only uses a single thread for the complete build or if the build process is on the linking process so all builds are being treated as equal. This overbooking of capacity turns out pretty well given that you have bunch of build stages where not all cores or each port are being utilized. If you have slower cores you'll likely benefit more by allocating more cores per port rather than build more ports in parallel due to dependency chains. At the same time you have to take into account the amount of RAM you have available, a good rule of thumb (in general) is about 1Gbyte / core because you want to avoid runnnig out of RAM and/or excessive swapping.

Disabling multi-threading in general rarely makes up for it.
 
Back
Top