/****************************************************** /* /* waiter children loop_size inner_loop_size sleep_time /* a simplified test case for linux load /* averages (way way way) too low issue. /* create children number of simultanious /* processes. Each process has a sleep_time /* (in microseconds). Tweek the computer dependent /* sleep frequency with loop_size. /* /* waiter.c Smythies 2012.05.06 /* Add load print out, so that I don't have to /* calculate it all the time. /* Note: there is not I/O wait with this program, /* so don't get excited that it isn't included in /* the math. /* /* waiter.c Smythies 2012.05.04 /* Try to make the sleep duration a variable. /* It is desired to test a very low load, but /* with a high enter exit idle frequency. /* /* waiter.c Smythies 2012.02.13 /* Forgot to edit a hard coded number to the /* define. This occured several versions ago. /* I didn't notice, because I usually abort, /* rather than let it finish now. /* /* waiter.c Smythies 2012.02.11 /* Make the inner loop count a run time /* variable. /* I almost always run this for a long time /* now, and then abort it, so just leave the /* outer loop as a define. I.E. I don't care /* much about the end of run stats anymore. /* /* waiter.c Smythies 2012.02.07 /* (Stupid) Error in freq calculations. /* /* waiter.c Smythies 2012.02.04 /* Try to add sleep frequency information. /* The newer hardware does not have the same /* frequencies for issues as the two older /* hardwares. /* Not coded well (hack to see if it will work). /* /* waiter.c Smythies 2012.02.02 /* This program is becoming usefull. Start /* a proper history header. /* /* waiter.c Smythies 2012:02:01. From book page 85. Hence /* the strange program name. /* Linux Programming By Example - Que /* /********************************************************/ #include #include #include #include #include #include #include # #define LOAD_F 20 #define OUTER_LOOP 180 #define MAX_SLEEP_TIME 999999 int main(int argc, char **argv){ clock_t start, end, last, parent_start, parent_end; struct tms t_start, t_end, t_parent_start, t_parent_end; long tps; pid_t child[LOAD_F]; int status, load_factor, inner_loop, inner_inner_loop; unsigned int sleep_time; int i,j,k,l,m; float parent_elapsed; switch(argc){ case 5: load_factor = atoi(argv[1]); inner_loop = atoi(argv[2]); inner_inner_loop = atoi(argv[3]); sleep_time = atoi(argv[4]); if(load_factor > LOAD_F){ load_factor = LOAD_F; printf("waiter: load factor clamped at maximum, %3d.\n", load_factor); } else { if(load_factor < 1){ load_factor = 1; printf("waiter: load factor clamped at minimum, %3d.\n", load_factor); } /* endif */ } /* endif */ if(inner_loop < 1){ inner_loop = 1; printf("waiter: loop size must be at least 1. Clamped it.\n"); } /* endif */ if(inner_inner_loop < 1){ inner_inner_loop = 1; printf("waiter: inner loop size must be at least 1. Clamped it.\n"); } /* endif */ if(sleep_time > MAX_SLEEP_TIME){ sleep_time = MAX_SLEEP_TIME; printf("waiter: sleep time clamped at maximum, %7u microseconds.\n", sleep_time); } else { if(sleep_time < 1){ sleep_time = 1; printf("waiter: sleep time clamped at minimum, %7u microseconds.\n", sleep_time); } /* endif */ } /* endif */ break; default: printf("waiter load_factor loop_size sleep_time (in microseconds)\n"); printf(" run load_factor instances of the CPU time waster, waiter.\n"); printf(" use loop_size to adjust the sleep frequency, because it depends on the computer and the sleep time.\n"); exit(-1); } /* endcase */ tps = sysconf(_SC_CLK_TCK); printf("waiter: ticks per second:%4ld\n", tps); parent_start = times(&t_parent_start); /* */ for(m = 0; m < load_factor; m++){ printf("waiter: process spawn loop%3d of%3d\n", m+1, load_factor); if((child[m] = fork()) == -1){ perror("fork"); exit(EXIT_FAILURE); } /* endif */ if(child[m] == 0){ start = times(&t_start); /* */ last = start; printf("\tchild %d pid = %d\n", m, getpid()); printf("\tchild %d ppid = %d\n", m, getppid()); for(i = 0; i < OUTER_LOOP; i++){ for(j = 0; j < inner_loop; j++){ for(k = 0; k < inner_inner_loop; k++){ l = i + j + k; } /* endfor */ usleep(sleep_time); } /* endfor */ end = times(&t_end); /* */ printf("Child%3d lp%5d of%5d: ", m, i + 1, OUTER_LOOP); printf("Elapsed:%7.2f s. ", ((float)(end - start) / (float)(tps))); /* */ printf("Delta:%7.2f s. ", ((float)(end - last) / (float)(tps))); /* */ printf("user cpu:%7.2f s. ", ((float)(t_end.tms_utime) / (float) (tps))); printf("sys cpu:%7.2f s. ", ((float)(t_end.tms_stime) / (float) (tps))); printf("load:%6.4f ", (float)(t_end.tms_stime + t_end.tms_utime) / (float)(end - start)); printf("last sleep freq.:%8.3f Hz. ", (float) inner_loop / ((float)(end - last) / (float)(tps))); printf("average sleep freq.:%8.3f Hz.\n", (float) inner_loop * (float ) (i + 1) / ((float)(end - start) / (float)(tps))); last = end; } /* endfor */ printf("Child%3d Total: ", m); printf("Elapsed:%7.2f s. ", ((float)(end - start) / (float)(tps))); /* */ printf("Delta:%9.4f s. (average)\n", ((float)(end - start) / (float) OUTER_LOOP / (float)(tps))); /* */ printf("\tchild %d pid = %d\n", m, getpid()); exit(EXIT_SUCCESS); } /* endif */ usleep(50000); } /* endfor */ puts("in parent .. about to start wait loops .."); printf("\tparent pid = %d\n", getpid()); printf("\tparent ppid = %d\n", getppid()); printf("\tparent pid = %d\n", getpid()); for(m = 0; m < load_factor; m++){ waitpid(0, &status, 0); printf("in parent after wait %3d Status: %d\n", m, status); } /* endfor */ parent_end = times(&t_parent_end); /* */ parent_elapsed = ((float)(parent_end - parent_start) / (float)(tps)); printf("Parent: "); printf("Elapsed:%7.2f s. ", parent_elapsed); /* */ printf("Throughput:%9.4f s. (average) ", parent_elapsed / (float) OUTER_LOOP / (float) load_factor); /* */ // The children are not included in the parent, so the below are at or near 0.00 // printf("user cpu:%9.2f s. ", ((float)(t_parent_end.tms_utime) / (float) (tps))); // printf("sys cpu:%9.2f s.\n", ((float)(t_parent_end.tms_stime) / (float) (tps))); printf("Delta:%9.4f s. (average) \n", parent_elapsed / (float) OUTER_LOOP); /* */ exit(EXIT_SUCCESS); } /* endprogram */