su_perf.c 4.15 KB
Newer Older
Pekka Pessi's avatar
Pekka Pessi committed
1 2 3 4 5 6 7
/*
 * This file is part of the Sofia-SIP package
 *
 * Copyright (C) 2005 Nokia Corporation.
 *
 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
 *
8
 * This library is free software; you can redistribute it and/or
Pekka Pessi's avatar
Pekka Pessi committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

/**@ingroup su_root_ex
 * @CFILE su_perf.c
 *
 * Performance test for su message passing
 *
 * @internal
31
 *
Pekka Pessi's avatar
Pekka Pessi committed
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 *
 * @date Created: Thu Mar 18 19:40:51 1999 pessi
 */

#include "config.h"

#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>

struct perf;
#define SU_ROOT_MAGIC_T struct perf
#define SU_MSG_ARG_T    struct message

48 49
#include "sofia-sip/su.h"
#include "sofia-sip/su_wait.h"
Pekka Pessi's avatar
Pekka Pessi committed
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82

struct perf {
  enum { PINGER = 1, PONGER = 2 } const sort;
  char const *const name;
  unsigned          running : 1;
  unsigned          target;
  unsigned          n;
  su_root_t        *root;
  struct sockaddr_in sin;
};

struct message {
  su_time_t started;
};

void
do_exit(struct perf *x, su_msg_r msg, struct message *m)
{
  su_root_break(su_task_root(su_msg_to(msg)));
}

int
do_init(su_root_t *root, struct perf *p)
{
  p->root = root;
  return 0;
}

void
do_print(struct perf *p, su_msg_r msg, struct message *m)
{
  su_time_t now = su_now();
  double dur = su_time_diff(now, m->started);
83

Pekka Pessi's avatar
Pekka Pessi committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
  printf("su_perf: %g message exchanges per second"
	 " (%d message exchanges in %g seconds)\n",
	 (double)p->n / dur, p->n, dur);
  su_msg_create(msg, su_root_parent(p->root), su_root_task(p->root),
		do_exit, sizeof(*m));
  *su_msg_data(msg) = *m;
  su_msg_send(msg);
}

void
do_ping(struct perf *p, su_msg_r msg, struct message *m)
{
  if (p->sort == PINGER) {
    p->n++;

    if (p->n % 100 == 0) {
      if (su_duration(su_now(), m->started) > p->target) {
	do_print(p, msg, m);
	return;
      }
    }
  }

  su_msg_reply(msg, msg, do_ping, sizeof(*m));
  *su_msg_data(msg) = *m;
  su_msg_send(msg);
}

void
do_destroy(su_root_t *t, struct perf *p)
{
  p->running = 0;
}

void usage(char *name)
{
  fprintf(stderr, "usage: %s [-1] [n]\n", name);
  exit(2);
}

/*
 * Measure how many message passes can be done in a second.
 *
 * Create a ponger and pinger, responding to incoming message do_ping
 *
129
 * After "target" rounds, print out elapsed time and number of messages
Pekka Pessi's avatar
Pekka Pessi committed
130 131 132 133 134 135 136 137 138
 * passed.
 *
 */
int main(int argc, char *argv[])
{
  su_root_t *root;
  su_clone_r ping = SU_CLONE_R_INIT, pong = SU_CLONE_R_INIT;
  su_msg_r start_msg = SU_MSG_R_INIT;

139 140
  struct perf
    pinger = { PINGER, "ping", 1, 0 },
Pekka Pessi's avatar
Pekka Pessi committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
    ponger = { PONGER, "pong", 1, 0x7fffffff};

  int have_threads = 1;
  char *argv0 = argv[0];
  char *argv1 = argv[1];

  if (argv1 && strcmp(argv1, "-1") == 0)
    have_threads = 0, argv1 = argv[2];

  if (!argv1)
    argv1 = "10000";

  if (strlen(argv1) != strspn(argv1, "0123456789"))
    usage(argv0);

  pinger.target = strtoul(argv1, NULL, 0);

  su_init(); atexit(su_deinit);

  root = su_root_create(NULL);
161

Pekka Pessi's avatar
Pekka Pessi committed
162 163 164 165 166
  su_root_threading(root, have_threads);

  if (su_clone_start(root, ping, &pinger, do_init, do_destroy) != 0)
    perror("su_clone_start"), exit(1);
  if (su_clone_start(root, pong, &ponger, do_init, do_destroy) != 0)
167
    perror("su_clone_start"), exit(1);
Pekka Pessi's avatar
Pekka Pessi committed
168

169
  if (su_msg_create(start_msg, su_clone_task(pong), su_clone_task(ping),
Pekka Pessi's avatar
Pekka Pessi committed
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
		    do_ping, sizeof(struct message)) == 0) {
    su_msg_data(start_msg)->started = su_now();
    su_msg_send(start_msg);

    su_root_run(root);
  }

#if 0
  su_clone_wait(root, ping);
  su_clone_wait(root, pong);

  while (pinger.running || ponger.running)
    su_root_step(root, 100L);
#endif

  su_root_destroy(root);

  return 0;
}