Open reddwarf69 opened 1 year ago
To have some numbers, I have a Jenkins slave with 64 cores. When pushing to a repository, multiple jobs are triggered. Those jobs are independent, and there is no easy way to have a common "jobserver" to limit the number of parallel tasks. All the makes/ninjas are run with "-j 64 -l 128".
With GNU Make 4.4 the peak 1 minute average load is 132, and the peak memory usage 55 GiB. With Ninja the peak 1 minute average load is 562, and the peak memory usage 222 GiB.
With GNU Make 4.4 it takes a 1.7% less time to complete (clean builds).
I'm not creating a PR because I'm not sure about the licence implications of me "basing" it on the GPL make patch. Maybe /proc/loadavg should be kept open the whole time instead of opening and closing in continuously, the parsing could maybe be made more robust, etc.
But this does the trick.
--- a/src/util.cc
+++ b/src/util.cc
@@ -818,6 +818,38 @@ double GetLoadAverage() {
double GetLoadAverage() {
return -0.0f;
}
+#elif defined(linux)
+double GetLoadAverage() {
+ int fd = open("/proc/loadavg", O_RDONLY);
+ if(fd == -1) {
+ return -0.0f;
+ }
+
+ char avg[65];
+ int size = read(fd, avg, 64);
+ close(fd);
+ if(size == -1) {
+ return -0.0f;
+ }
+ avg[size] = '\0';
+
+ const char *p = strchr(avg, ' ');
+ if (p) {
+ p = strchr(p+1, ' ');
+ }
+ if (p) {
+ p = strchr(p+1, ' ');
+ }
+ if (!p) {
+ return -0.0f;
+ }
+
+ if((unsigned)p[1] - '0' > 9) {
+ return -0.0f;
+ }
+
+ return atoi(p+1);
+}
#else
double GetLoadAverage() {
double loadavg[3] = { 0.0f, 0.0f, 0.0f };
0001-Use-proc-loadavg-on-Linux.log
I'm using it in production and my builds are now a 6.7% faster than without the patch (plus the OOM killer never kills them).
I'm not sure about the licence implications of me "basing" it on the GPL make patch.
There is none if you don't the copy code. If you just take the idea and reimplement it in a different program then that is fine.
Yeah, this would be pretty convenient. Given that ninja still doesn't support the GNU jobserver (#1139) , supporting /proc/loadavg
would be a possibly simpler way to deal with the issue of many ninja
instances spawned somewhere down the line by make -j <n>
.
GNU Make uses /proc/loadavg on Linux to decide whether to start another task: https://lwn.net/Articles/913253/ / https://git.savannah.gnu.org/cgit/make.git/commit/src/job.c?id=d8728efc80b720c630e6b12dbd34a3d44e060690. I would like Ninja to do the same.
Since /proc/loadavg provides "number of processes currently runnable (running or on ready queue)" (https://www.kernel.org/doc/html/latest/filesystems/proc.html), Ninja would be able to take better decisions than by looking only at the info provided by getloadavg().