1 #undef G_DISABLE_ASSERT
9 #include <sys/resource.h>
13 static int n_children
= 3;
14 static int n_active_children
;
15 static int n_iters
= 10000;
16 static GMainLoop
*loop
;
19 io_pipe (GIOChannel
**channels
)
25 fprintf (stderr
, "Cannot create pipe %s\n", g_strerror (errno
));
29 channels
[0] = g_io_channel_unix_new (fds
[0]);
30 channels
[1] = g_io_channel_unix_new (fds
[1]);
34 read_all (GIOChannel
*channel
, char *buf
, int len
)
40 while (bytes_read
< len
)
42 err
= g_io_channel_read (channel
, buf
+ bytes_read
, len
- bytes_read
, &count
);
45 if (err
!= G_IO_ERROR_AGAIN
)
58 write_all (GIOChannel
*channel
, char *buf
, int len
)
60 gsize bytes_written
= 0;
64 while (bytes_written
< len
)
66 err
= g_io_channel_write (channel
, buf
+ bytes_written
, len
- bytes_written
, &count
);
67 if (err
&& err
!= G_IO_ERROR_AGAIN
)
70 bytes_written
+= count
;
77 run_child (GIOChannel
*in_channel
, GIOChannel
*out_channel
)
81 GTimer
*timer
= g_timer_new();
83 for (i
= 0; i
< n_iters
; i
++)
85 write_all (out_channel
, (char *)&val
, sizeof (val
));
86 read_all (in_channel
, (char *)&val
, sizeof (val
));
90 write_all (out_channel
, (char *)&val
, sizeof (val
));
92 val
= g_timer_elapsed (timer
, NULL
) * 1000;
94 write_all (out_channel
, (char *)&val
, sizeof (val
));
95 g_timer_destroy (timer
);
101 input_callback (GIOChannel
*source
,
102 GIOCondition condition
,
106 GIOChannel
*dest
= (GIOChannel
*)data
;
108 if (!read_all (source
, (char *)&val
, sizeof(val
)))
110 fprintf (stderr
, "Unexpected EOF\n");
116 write_all (dest
, (char *)&val
, sizeof(val
));
122 g_io_channel_close (source
);
123 g_io_channel_close (dest
);
125 g_io_channel_unref (source
);
126 g_io_channel_unref (dest
);
129 if (n_active_children
== 0)
130 g_main_loop_quit (loop
);
140 GIOChannel
*in_channels
[2];
141 GIOChannel
*out_channels
[2];
143 io_pipe (in_channels
);
144 io_pipe (out_channels
);
148 if (pid
> 0) /* Parent */
150 g_io_channel_close (in_channels
[0]);
151 g_io_channel_unref (in_channels
[0]);
152 g_io_channel_close (out_channels
[1]);
153 g_io_channel_unref (out_channels
[1]);
155 g_io_add_watch (out_channels
[0], G_IO_IN
| G_IO_HUP
,
156 input_callback
, in_channels
[1]);
158 else if (pid
== 0) /* Child */
160 g_io_channel_close (in_channels
[1]);
161 g_io_channel_close (out_channels
[0]);
165 run_child (in_channels
[0], out_channels
[1]);
169 fprintf (stderr
, "Cannot fork: %s\n", g_strerror (errno
));
175 difftimeval (struct timeval
*old
, struct timeval
*new)
178 (new->tv_sec
- old
->tv_sec
) * 1000. + (new->tv_usec
- old
->tv_usec
) / 1000;
182 main (int argc
, char **argv
)
185 struct rusage old_usage
;
186 struct rusage new_usage
;
189 n_children
= atoi(argv
[1]);
192 n_iters
= atoi(argv
[2]);
194 printf ("Children: %d Iters: %d\n", n_children
, n_iters
);
196 n_active_children
= n_children
;
197 for (i
= 0; i
< n_children
; i
++)
200 getrusage (RUSAGE_SELF
, &old_usage
);
201 loop
= g_main_loop_new (NULL
, FALSE
);
202 g_main_loop_run (loop
);
203 getrusage (RUSAGE_SELF
, &new_usage
);
205 printf ("Elapsed user: %g\n",
206 difftimeval (&old_usage
.ru_utime
, &new_usage
.ru_utime
));
207 printf ("Elapsed system: %g\n",
208 difftimeval (&old_usage
.ru_stime
, &new_usage
.ru_stime
));
209 printf ("Elapsed total: %g\n",
210 difftimeval (&old_usage
.ru_utime
, &new_usage
.ru_utime
) +
211 difftimeval (&old_usage
.ru_stime
, &new_usage
.ru_stime
));
212 printf ("total / iteration: %g\n",
213 (difftimeval (&old_usage
.ru_utime
, &new_usage
.ru_utime
) +
214 difftimeval (&old_usage
.ru_stime
, &new_usage
.ru_stime
)) /
215 (n_iters
* n_children
));
217 g_main_loop_unref (loop
);