Darryl Gove's blog
putc in a multithreaded context
Just answering a question from a colleague. The application was running significantly slower when compiled as a multithreaded app compared to the original serial app. The profile showed mutex_unlock as being hot, but going up the callstack the routine that called mutex_unlock was putc.
This is the OpenSolaris source for putc, which shows a call to FLOCKFILE, which is defined in this file for MT programs. So for MT programs, a lock needs to be acquired before the character can be output.
Fortunately it is possible to avoid the locking using putc_unlocked. This call should not be used as a drop-in replacement for putc, but used after the appropriate mutex has been acquired. The details are in the Solaris Multi-threaded programming guide.
A test program that demonstrates this problem is:
#include <stdio.h>
#include <pthread.h>
#include <sys/time.h>
static double s_time;
void starttime()
{
s_time=1.0*gethrtime();
}
void endtime(long its)
{
double e_time=1.0*gethrtime();
printf("Time per iteration %5.2f ns\n", (e_time-s_time)/(1.0*its));
s_time=1.0*gethrtime();
}
void *dowork(void *params)
{
starttime();
FILE* s=fopen("/tmp/dldldldldld","w");
for (int i=0; i<100000000; i++)
{
putc(65,s);
}
fclose(s);
endtime(100000000);
}
void main()
{
starttime();
FILE* s=fopen("/tmp/dldldldldld","w");
for (int i=0; i<100000000; i++)
{
putc(65,s);
}
fclose(s);
endtime(100000000);
pthread_t threads[1];
pthread_create(&threads[0],NULL,dowork,NULL);
pthread_join(threads[0],NULL);
}
Here's the results of running the code on Solaris 10:
$ cc -mt putc.c Time per iteration 30.55 ns Time per iteration 165.76 ns
The situation on Solaris 10 is better than Solaris 9, since on Solaris 9 the cost of the mutex was incurred by the -mt compiler flag rather than whether there were actually multiple threads active.
Posted at 03:13PM Jan 07, 2008 by Darryl Gove in Sun |
