1 #undef G_DISABLE_ASSERT
9 #include <sys/resource.h>
12 #include <glib-object.h>
14 static int n_children
= 3;
15 static int n_active_children
;
16 static int n_iters
= 10000;
17 static GMainLoop
*loop
;
20 io_pipe (GIOChannel
**channels
)
26 fprintf (stderr
, "Cannot create pipe %s\n", g_strerror (errno
));
30 channels
[0] = g_io_channel_unix_new (fds
[0]);
31 channels
[1] = g_io_channel_unix_new (fds
[1]);
35 read_all (GIOChannel
*channel
, char *buf
, int len
)
41 while (bytes_read
< len
)
43 err
= g_io_channel_read (channel
, buf
+ bytes_read
, len
- bytes_read
, &count
);
46 if (err
!= G_IO_ERROR_AGAIN
)
59 write_all (GIOChannel
*channel
, char *buf
, int len
)
61 gsize bytes_written
= 0;
65 while (bytes_written
< len
)
67 err
= g_io_channel_write (channel
, buf
+ bytes_written
, len
- bytes_written
, &count
);
68 if (err
&& err
!= G_IO_ERROR_AGAIN
)
71 bytes_written
+= count
;
78 run_child (GIOChannel
*in_channel
, GIOChannel
*out_channel
)
82 GTimer
*timer
= g_timer_new();
84 for (i
= 0; i
< n_iters
; i
++)
86 write_all (out_channel
, (char *)&val
, sizeof (val
));
87 read_all (in_channel
, (char *)&val
, sizeof (val
));
91 write_all (out_channel
, (char *)&val
, sizeof (val
));
93 val
= g_timer_elapsed (timer
, NULL
) * 1000;
95 write_all (out_channel
, (char *)&val
, sizeof (val
));
96 g_timer_destroy (timer
);
102 input_callback (GIOChannel
*source
,
103 GIOCondition condition
,
107 GIOChannel
*dest
= (GIOChannel
*)data
;
109 if (!read_all (source
, (char *)&val
, sizeof(val
)))
111 fprintf (stderr
, "Unexpected EOF\n");
117 write_all (dest
, (char *)&val
, sizeof(val
));
123 g_io_channel_close (source
);
124 g_io_channel_close (dest
);
127 if (n_active_children
== 0)
128 g_main_loop_quit (loop
);
138 GIOChannel
*in_channels
[2];
139 GIOChannel
*out_channels
[2];
142 io_pipe (in_channels
);
143 io_pipe (out_channels
);
147 if (pid
> 0) /* Parent */
149 g_io_channel_close (in_channels
[0]);
150 g_io_channel_close (out_channels
[1]);
152 source
= g_io_create_watch (out_channels
[0], G_IO_IN
| G_IO_HUP
);
153 g_source_set_closure (source
,
154 g_cclosure_new (G_CALLBACK (input_callback
), in_channels
[1],
155 (GClosureNotify
)g_io_channel_unref
));
156 g_source_attach (source
, NULL
);
157 g_source_unref (source
);
159 g_io_channel_unref (in_channels
[0]);
160 g_io_channel_unref (out_channels
[0]);
161 g_io_channel_unref (out_channels
[1]);
164 else if (pid
== 0) /* Child */
166 g_io_channel_close (in_channels
[1]);
167 g_io_channel_close (out_channels
[0]);
171 run_child (in_channels
[0], out_channels
[1]);
175 fprintf (stderr
, "Cannot fork: %s\n", g_strerror (errno
));
181 difftimeval (struct timeval
*old
, struct timeval
*new)
184 (new->tv_sec
- old
->tv_sec
) * 1000. + (new->tv_usec
- old
->tv_usec
) / 1000;
188 main (int argc
, char **argv
)
191 struct rusage old_usage
;
192 struct rusage new_usage
;
195 n_children
= atoi(argv
[1]);
198 n_iters
= atoi(argv
[2]);
200 printf ("Children: %d Iters: %d\n", n_children
, n_iters
);
202 n_active_children
= n_children
;
203 for (i
= 0; i
< n_children
; i
++)
206 getrusage (RUSAGE_SELF
, &old_usage
);
207 loop
= g_main_loop_new (NULL
, FALSE
);
208 g_main_loop_run (loop
);
209 getrusage (RUSAGE_SELF
, &new_usage
);
211 printf ("Elapsed user: %g\n",
212 difftimeval (&old_usage
.ru_utime
, &new_usage
.ru_utime
));
213 printf ("Elapsed system: %g\n",
214 difftimeval (&old_usage
.ru_stime
, &new_usage
.ru_stime
));
215 printf ("Elapsed total: %g\n",
216 difftimeval (&old_usage
.ru_utime
, &new_usage
.ru_utime
) +
217 difftimeval (&old_usage
.ru_stime
, &new_usage
.ru_stime
));
218 printf ("total / iteration: %g\n",
219 (difftimeval (&old_usage
.ru_utime
, &new_usage
.ru_utime
) +
220 difftimeval (&old_usage
.ru_stime
, &new_usage
.ru_stime
)) /
221 (n_iters
* n_children
));
223 g_main_loop_unref (loop
);