Matthias Andree writes:
Who's gonna remove them?In case you've missed it, I'll repeat my suggestion: I suggested keeping the tmp/timestamp.pid.hostname files for a finite amount of time after linking them to new/ (so that for 20 seconds or 2 seconds or what timeout you choose, both file names exist) -- the tmp/ is then a kind of
You want qmail-local, or whatever delivers the message, to sleep around, with its thumb up its ass for 2-20 seconds, before unlinking the tmp file, and exiting?
It doesn't matter how many CPUs the machine has. If microseconds are added to the filename, you have to turn things around in less than a microsecond for the race to remain (I might've messed up my units a few times in the last couple of days, but I'm always referring to tv_usec's, one millionth of a second). It takes a finite amount of CPU instructions to clean up an existing process, then set up another one, and start running it. That number of CPU instructions does not change no matter how many CPUs are in there. They have to be executed in turn. At different times, different CPUs might be running the code (and adding the overhead of context switches to the whole mix), but there's a definite starting point, and a definite ending point here, and the whole show must occur in less than a microsecond in order for the race to still exist.Some 16-processor machine with huge caches might have a real problem sooner than we want...
I've ran the RAM bandwidth numbers before. It's out of the second. You say something about large CPU caches. Still, the CPU has to run them. Assume everything is in the L1 cache, with zero latency. Assume the CPU requires 5 cycles for an average instruction. My abacus says that a 1Ghz CPU will execute 200 instructions per microsecond.
Let's measure CPU latency. Let's try to have everything cached:
struct timeval tv_array[100];
int i;
for (i=0; i<sizeof(tv_array)/sizeof(tv_array[0]); i++)
gettimeofday(&tv_array[i], NULL);
for (i=0; i<sizeof(tv_array)/sizeof(tv_array[0]); i++)
printf("%06d\n", tv_array[i].tv_usec);
The output, on a box with a pair of 1.13 Ghz CPUs, no other load, shows that the first loop executes a max number of three times per microsecond.
Divide that into the ratio of the complexity between this loop, and the code to tear down one process, and build another process, and draw your own conclusions.
I actually had another brainstorm today. Add the file's inode, when moving the message from tmp to new:
tmp/timestamp.unique_pid.hostname -> new/timestamp.inode.unique_pid.hostname
How does that grab you? It does add an extra stat() call, to obtain the message's inode, after the file is created in tmp.
