glib/tests/timeloop-basic.c
changeset 18 47c74d1534e1
child 34 5fae379060a7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/tests/timeloop-basic.c	Fri Apr 16 16:46:38 2010 +0300
@@ -0,0 +1,252 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+#undef G_DISABLE_ASSERT
+#undef G_LOG_DOMAIN
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+
+#define TRUE 1
+#define FALSE 0
+
+static int n_children = 3;
+static int n_active_children;
+static int n_iters = 10000;
+
+static int write_fds[1024];
+static struct pollfd poll_fds[1024];
+
+void
+my_pipe (int *fds)
+{
+  if (pipe(fds) < 0)
+    {
+      fprintf (stderr, "Cannot create pipe %s\n", strerror (errno));
+      exit (1);
+    }
+}
+
+int
+read_all (int fd, char *buf, int len)
+{
+  size_t bytes_read = 0;
+  ssize_t count;
+
+  while (bytes_read < len)
+    {
+      count = read (fd, buf + bytes_read, len - bytes_read);
+      if (count < 0)
+	{
+	  if (errno != EAGAIN)
+	    return FALSE;
+	}
+      else if (count == 0)
+	return FALSE;
+
+      bytes_read += count;
+    }
+
+  return TRUE;
+}
+
+int
+write_all (int fd, char *buf, int len)
+{
+  size_t bytes_written = 0;
+  ssize_t count;
+
+  while (bytes_written < len)
+    {
+      count = write (fd, buf + bytes_written, len - bytes_written);
+      if (count < 0)
+	{
+	  if (errno != EAGAIN)
+	    return FALSE;
+	}
+
+      bytes_written += count;
+    }
+
+  return TRUE;
+}
+
+void
+run_child (int in_fd, int out_fd)
+{
+  int i;
+  int val = 1;
+
+  for (i = 0; i < n_iters; i++)
+    {
+      write_all (out_fd, (char *)&val, sizeof (val));
+      read_all (in_fd, (char *)&val, sizeof (val));
+    }
+
+  val = 0;
+  write_all (out_fd, (char *)&val, sizeof (val));
+
+  exit (0);
+}
+
+int
+input_callback (int source, int dest)
+{
+  int val;
+  
+  if (!read_all (source, (char *)&val, sizeof(val)))
+    {
+      fprintf (stderr,"Unexpected EOF\n");
+      exit (1);
+    }
+
+  if (val)
+    {
+      write_all (dest, (char *)&val, sizeof(val));
+      return TRUE;
+    }
+  else
+    {
+      close (source);
+      close (dest);
+      
+      n_active_children--;
+      return FALSE;
+    }
+}
+
+void
+create_child (int pos)
+{
+  int pid;
+  int in_fds[2];
+  int out_fds[2];
+  
+  my_pipe (in_fds);
+  my_pipe (out_fds);
+
+  pid = fork ();
+
+  if (pid > 0)			/* Parent */
+    {
+      close (in_fds[0]);
+      close (out_fds[1]);
+
+      write_fds[pos] = in_fds[1];
+      poll_fds[pos].fd = out_fds[0];
+      poll_fds[pos].events = POLLIN;
+    }
+  else if (pid == 0)		/* Child */
+    {
+      close (in_fds[1]);
+      close (out_fds[0]);
+
+      setsid ();
+
+      run_child (in_fds[0], out_fds[1]);
+    }
+  else				/* Error */
+    {
+      fprintf (stderr,"Cannot fork: %s\n", strerror (errno));
+      exit (1);
+    }
+}
+
+static double 
+difftimeval (struct timeval *old, struct timeval *new)
+{
+  return
+    (new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000;
+}
+
+int 
+main (int argc, char **argv)
+{
+  int i, j;
+  struct rusage old_usage;
+  struct rusage new_usage;
+  
+  if (argc > 1)
+    n_children = atoi(argv[1]);
+
+  if (argc > 2)
+    n_iters = atoi(argv[2]);
+
+  printf ("Children: %d     Iters: %d\n", n_children, n_iters);
+
+  n_active_children = n_children;
+  for (i = 0; i < n_children; i++)
+    create_child (i);
+
+  getrusage (RUSAGE_SELF, &old_usage);
+
+  while (n_active_children > 0)
+    {
+      int old_n_active_children = n_active_children;
+
+      poll (poll_fds, n_active_children, -1);
+
+      for (i=0; i<n_active_children; i++)
+	{
+	  if (poll_fds[i].events & (POLLIN | POLLHUP))
+	    {
+	      if (!input_callback (poll_fds[i].fd, write_fds[i]))
+		write_fds[i] = -1;
+	    }
+	}
+
+      if (old_n_active_children > n_active_children)
+	{
+	  j = 0;
+	  for (i=0; i<old_n_active_children; i++)
+	    {
+	      if (write_fds[i] != -1)
+		{
+		  if (j < i)
+		    {
+		      poll_fds[j] = poll_fds[i];
+		      write_fds[j] = write_fds[i];
+		    }
+		  j++;
+		}
+	    }
+	}
+    }
+
+  getrusage (RUSAGE_SELF, &new_usage);
+
+  printf ("Elapsed user: %g\n",
+	   difftimeval (&old_usage.ru_utime, &new_usage.ru_utime));
+  printf ("Elapsed system: %g\n",
+	   difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
+  printf ("Elapsed total: %g\n",
+	  difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +	   
+	   difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
+  printf ("total / iteration: %g\n",
+	   (difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +	   
+	    difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) /
+	   (n_iters * n_children));
+
+  return 0;
+}
+