source: trunk/third/glib2/tests/timeloop.c @ 18159

Revision 18159, 4.4 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18158, which included commits to RCS files with non-trunk default branches.
Line 
1#undef G_DISABLE_ASSERT
2#undef G_LOG_DOMAIN
3
4#include <errno.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <stdio.h>
8#include <sys/time.h>
9#include <sys/resource.h>
10
11#include <glib.h>
12
13static int n_children = 3;
14static int n_active_children;
15static int n_iters = 10000;
16static GMainLoop *loop;
17
18static void
19io_pipe (GIOChannel **channels)
20{
21  int fds[2];
22
23  if (pipe(fds) < 0)
24    {
25      fprintf (stderr, "Cannot create pipe %s\n", g_strerror (errno));
26      exit (1);
27    }
28
29  channels[0] = g_io_channel_unix_new (fds[0]);
30  channels[1] = g_io_channel_unix_new (fds[1]);
31}
32
33static gboolean
34read_all (GIOChannel *channel, char *buf, int len)
35{
36  gsize bytes_read = 0;
37  gsize count;
38  GIOError err;
39
40  while (bytes_read < len)
41    {
42      err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count);
43      if (err)
44        {
45          if (err != G_IO_ERROR_AGAIN)
46            return FALSE;
47        }
48      else if (count == 0)
49        return FALSE;
50
51      bytes_read += count;
52    }
53
54  return TRUE;
55}
56
57static gboolean
58write_all (GIOChannel *channel, char *buf, int len)
59{
60  gsize bytes_written = 0;
61  gsize count;
62  GIOError err;
63
64  while (bytes_written < len)
65    {
66      err = g_io_channel_write (channel, buf + bytes_written, len - bytes_written, &count);
67      if (err && err != G_IO_ERROR_AGAIN)
68        return FALSE;
69
70      bytes_written += count;
71    }
72
73  return TRUE;
74}
75
76static void
77run_child (GIOChannel *in_channel, GIOChannel *out_channel)
78{
79  int i;
80  int val = 1;
81  GTimer *timer = g_timer_new();
82
83  for (i = 0; i < n_iters; i++)
84    {
85      write_all (out_channel, (char *)&val, sizeof (val));
86      read_all (in_channel, (char *)&val, sizeof (val));
87    }
88
89  val = 0;
90  write_all (out_channel, (char *)&val, sizeof (val));
91
92  val = g_timer_elapsed (timer, NULL) * 1000;
93 
94  write_all (out_channel, (char *)&val, sizeof (val));
95  g_timer_destroy (timer);
96
97  exit (0);
98}
99
100static gboolean
101input_callback (GIOChannel   *source,
102                GIOCondition  condition,
103                gpointer      data)
104{
105  int val;
106  GIOChannel *dest = (GIOChannel *)data;
107 
108  if (!read_all (source, (char *)&val, sizeof(val)))
109    {
110      fprintf (stderr, "Unexpected EOF\n");
111      exit (1);
112    }
113
114  if (val)
115    {
116      write_all (dest, (char *)&val, sizeof(val));
117     
118      return TRUE;
119    }
120  else
121    {
122      g_io_channel_close (source);
123      g_io_channel_close (dest);
124     
125      g_io_channel_unref (source);
126      g_io_channel_unref (dest);
127
128      n_active_children--;
129      if (n_active_children == 0)
130        g_main_loop_quit (loop);
131     
132      return FALSE;
133    }
134}
135
136static void
137create_child ()
138{
139  int pid;
140  GIOChannel *in_channels[2];
141  GIOChannel *out_channels[2];
142 
143  io_pipe (in_channels);
144  io_pipe (out_channels);
145
146  pid = fork ();
147
148  if (pid > 0)                  /* Parent */
149    {
150      g_io_channel_close (in_channels[0]);
151      g_io_channel_close (out_channels[1]);
152
153      g_io_add_watch (out_channels[0], G_IO_IN | G_IO_HUP,
154                      input_callback, in_channels[1]);
155    }
156  else if (pid == 0)            /* Child */
157    {
158      g_io_channel_close (in_channels[1]);
159      g_io_channel_close (out_channels[0]);
160
161      setsid ();
162
163      run_child (in_channels[0], out_channels[1]);
164    }
165  else                          /* Error */
166    {
167      fprintf (stderr, "Cannot fork: %s\n", g_strerror (errno));
168      exit (1);
169    }
170}
171
172static double
173difftimeval (struct timeval *old, struct timeval *new)
174{
175  return
176    (new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000;
177}
178
179int
180main (int argc, char **argv)
181{
182  int i;
183  struct rusage old_usage;
184  struct rusage new_usage;
185 
186  if (argc > 1)
187    n_children = atoi(argv[1]);
188
189  if (argc > 2)
190    n_iters = atoi(argv[2]);
191
192  printf ("Children: %d     Iters: %d\n", n_children, n_iters);
193
194  n_active_children = n_children;
195  for (i = 0; i < n_children; i++)
196    create_child ();
197
198  getrusage (RUSAGE_SELF, &old_usage);
199  loop = g_main_loop_new (NULL, FALSE);
200  g_main_loop_run (loop);
201  getrusage (RUSAGE_SELF, &new_usage);
202
203  printf ("Elapsed user: %g\n",
204          difftimeval (&old_usage.ru_utime, &new_usage.ru_utime));
205  printf ("Elapsed system: %g\n",
206          difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
207  printf ("Elapsed total: %g\n",
208          difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +         
209          difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
210  printf ("total / iteration: %g\n",
211          (difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +       
212           difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) /
213          (n_iters * n_children));
214
215  return 0;
216}
Note: See TracBrowser for help on using the repository browser.