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
)
27 fprintf (stderr
, "Cannot create pipe %s\n", g_strerror (errsv
));
31 channels
[0] = g_io_channel_unix_new (fds
[0]);
32 channels
[1] = g_io_channel_unix_new (fds
[1]);
36 read_all (GIOChannel
*channel
, char *buf
, int len
)
42 while (bytes_read
< len
)
44 err
= g_io_channel_read (channel
, buf
+ bytes_read
, len
- bytes_read
, &count
);
47 if (err
!= G_IO_ERROR_AGAIN
)
60 write_all (GIOChannel
*channel
, char *buf
, int len
)
62 gsize bytes_written
= 0;
66 while (bytes_written
< len
)
68 err
= g_io_channel_write (channel
, buf
+ bytes_written
, len
- bytes_written
, &count
);
69 if (err
&& err
!= G_IO_ERROR_AGAIN
)
72 bytes_written
+= count
;
79 run_child (GIOChannel
*in_channel
, GIOChannel
*out_channel
)
83 GTimer
*timer
= g_timer_new();
85 for (i
= 0; i
< n_iters
; i
++)
87 write_all (out_channel
, (char *)&val
, sizeof (val
));
88 read_all (in_channel
, (char *)&val
, sizeof (val
));
92 write_all (out_channel
, (char *)&val
, sizeof (val
));
94 val
= g_timer_elapsed (timer
, NULL
) * 1000;
96 write_all (out_channel
, (char *)&val
, sizeof (val
));
97 g_timer_destroy (timer
);
103 input_callback (GIOChannel
*source
,
104 GIOCondition condition
,
108 GIOChannel
*dest
= (GIOChannel
*)data
;
110 if (!read_all (source
, (char *)&val
, sizeof(val
)))
112 fprintf (stderr
, "Unexpected EOF\n");
118 write_all (dest
, (char *)&val
, sizeof(val
));
124 g_io_channel_close (source
);
125 g_io_channel_close (dest
);
128 if (n_active_children
== 0)
129 g_main_loop_quit (loop
);
139 GIOChannel
*in_channels
[2];
140 GIOChannel
*out_channels
[2];
143 io_pipe (in_channels
);
144 io_pipe (out_channels
);
149 if (pid
> 0) /* Parent */
151 g_io_channel_close (in_channels
[0]);
152 g_io_channel_close (out_channels
[1]);
154 source
= g_io_create_watch (out_channels
[0], G_IO_IN
| G_IO_HUP
);
155 g_source_set_closure (source
,
156 g_cclosure_new (G_CALLBACK (input_callback
), in_channels
[1],
157 (GClosureNotify
)g_io_channel_unref
));
158 g_source_attach (source
, NULL
);
159 g_source_unref (source
);
161 g_io_channel_unref (in_channels
[0]);
162 g_io_channel_unref (out_channels
[0]);
163 g_io_channel_unref (out_channels
[1]);
166 else if (pid
== 0) /* Child */
168 g_io_channel_close (in_channels
[1]);
169 g_io_channel_close (out_channels
[0]);
173 run_child (in_channels
[0], out_channels
[1]);
177 fprintf (stderr
, "Cannot fork: %s\n", g_strerror (errsv
));
183 difftimeval (struct timeval
*old
, struct timeval
*new)
186 (new->tv_sec
- old
->tv_sec
) * 1000. + (new->tv_usec
- old
->tv_usec
) / 1000;
190 main (int argc
, char **argv
)
193 struct rusage old_usage
;
194 struct rusage new_usage
;
197 n_children
= atoi(argv
[1]);
200 n_iters
= atoi(argv
[2]);
202 printf ("Children: %d Iters: %d\n", n_children
, n_iters
);
204 n_active_children
= n_children
;
205 for (i
= 0; i
< n_children
; i
++)
208 getrusage (RUSAGE_SELF
, &old_usage
);
209 loop
= g_main_loop_new (NULL
, FALSE
);
210 g_main_loop_run (loop
);
211 getrusage (RUSAGE_SELF
, &new_usage
);
213 printf ("Elapsed user: %g\n",
214 difftimeval (&old_usage
.ru_utime
, &new_usage
.ru_utime
));
215 printf ("Elapsed system: %g\n",
216 difftimeval (&old_usage
.ru_stime
, &new_usage
.ru_stime
));
217 printf ("Elapsed total: %g\n",
218 difftimeval (&old_usage
.ru_utime
, &new_usage
.ru_utime
) +
219 difftimeval (&old_usage
.ru_stime
, &new_usage
.ru_stime
));
220 printf ("total / iteration: %g\n",
221 (difftimeval (&old_usage
.ru_utime
, &new_usage
.ru_utime
) +
222 difftimeval (&old_usage
.ru_stime
, &new_usage
.ru_stime
)) /
223 (n_iters
* n_children
));
225 g_main_loop_unref (loop
);