lat_msg.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * lat_msgqueue.c - simple message queue latency test
  3. *
  4. * Three programs in one -
  5. * server usage: tcp_xact -s
  6. * client usage: tcp_xact hostname
  7. * shutwn: tcp_xact -hostname
  8. *
  9. * Copyright (c) 1994 Larry McVoy. Distributed under the FSF GPL with
  10. * additional restriction that results may published only if
  11. * (1) the benchmark is unmodified, and
  12. * (2) the version in the sccsid below is included in the report.
  13. * Support for this development by Sun Microsystems is gratefully acknowledged.
  14. */
  15. char *id = "$Id$\n";
  16. #include "bench.h"
  17. #include <sys/ipc.h>
  18. #include <sys/msg.h>
  19. int
  20. create_q(int key)
  21. {
  22. return msgget(key, IPC_CREAT|0600);
  23. }
  24. int
  25. open_q(int key)
  26. {
  27. return msgget(key, 0);
  28. }
  29. void
  30. close_q(int id)
  31. {
  32. msgctl(id, IPC_RMID, NULL);
  33. }
  34. void
  35. create_close_q(int key)
  36. {
  37. int id = create_q(key);
  38. close_q(id);
  39. }
  40. void
  41. create_open_close_q(int key)
  42. {
  43. int id = create_q(key);
  44. open_q(key);
  45. close_q(id);
  46. }
  47. void
  48. create_server(int pipes[2])
  49. {
  50. int i, begin = 0, end = 0;
  51. int key, id = 0;
  52. while (read(pipes[0], &key, sizeof(int)) == sizeof(int)) {
  53. if (id) close_q(id);
  54. id = create_q(key);
  55. if (write(pipes[1], &id, sizeof(int)) < sizeof(int)) {
  56. perror("write");
  57. exit(1);
  58. }
  59. }
  60. if (id) close_q(id);
  61. }
  62. int
  63. client_create_q(int pipes[2], int key)
  64. {
  65. int id;
  66. if (write(pipes[1], &key, sizeof(int)) < sizeof(int)) {
  67. perror("write");
  68. exit(1);
  69. }
  70. if (read(pipes[0], &id, sizeof(int)) < sizeof(int)) {
  71. perror("read");
  72. exit(1);
  73. }
  74. return id;
  75. }
  76. int
  77. client_create_open_q(int pipes[2], int key)
  78. {
  79. int id;
  80. if (write(pipes[1], &key, sizeof(int)) < sizeof(int)) {
  81. perror("write");
  82. exit(1);
  83. }
  84. if (read(pipes[0], &id, sizeof(int)) < sizeof(int)) {
  85. perror("read");
  86. exit(1);
  87. }
  88. return open_q(key);
  89. }
  90. void
  91. send_q(int *id, int n)
  92. {
  93. if (n % 5000 == 0) {
  94. close_q(*id);
  95. *id = create_q(0);
  96. }
  97. struct {
  98. long mtype;
  99. char mtext[1];
  100. } buf;
  101. buf.mtype = 1;
  102. msgsnd(*id, &buf, 1, 0);
  103. }
  104. void
  105. receive_q(int id)
  106. {
  107. struct {
  108. long mtype;
  109. char mtext[1];
  110. } buf;
  111. if (msgrcv(id, &buf, 1, 1, 0) < 1) {
  112. perror("msgrcv");
  113. exit(1);
  114. }
  115. }
  116. void
  117. send_receive_q(int *id, int n)
  118. {
  119. send_q(id, n);
  120. receive_q(*id);
  121. }
  122. void
  123. send_server(int pipes[2], int *id)
  124. {
  125. int n;
  126. while (read(pipes[0], &n, sizeof(int)) == sizeof(int)) {
  127. send_q(id, n);
  128. if (write(pipes[1], id, sizeof(int)) < sizeof(int)) {
  129. perror("write");
  130. exit(1);
  131. }
  132. }
  133. }
  134. void
  135. client_send_q(int pipes[2], int n)
  136. {
  137. int id;
  138. if (write(pipes[1], &n, sizeof(int)) < sizeof(int)) {
  139. perror("write");
  140. exit(1);
  141. }
  142. if (read(pipes[0], &id, sizeof(int)) < sizeof(int)) {
  143. perror("read");
  144. exit(1);
  145. }
  146. }
  147. void
  148. client_send_receive_q(int pipes[2], int n)
  149. {
  150. int id;
  151. if (write(pipes[1], &n, sizeof(int)) < sizeof(int)) {
  152. perror("write");
  153. exit(1);
  154. }
  155. if (read(pipes[0], &id, sizeof(int)) < sizeof(int)) {
  156. perror("read");
  157. exit(1);
  158. }
  159. receive_q(id);
  160. }
  161. int
  162. main(int ac, char **av)
  163. {
  164. if (ac < 2) goto usage;
  165. if (!strcmp("create", av[1])) {
  166. int i, cnt = 0;
  167. BENCH(create_close_q(++cnt), REAL_SHORT);
  168. micro("message queue creation and close latency", get_n());
  169. } else if (!strcmp("fork-create", av[1])) {
  170. if (fork() == 0) {
  171. int i, cnt = 0;
  172. BENCH(create_close_q(++cnt), REAL_SHORT);
  173. micro("message queue creation lnd close atency after fork",
  174. get_n());
  175. exit(0);
  176. }
  177. wait(NULL);
  178. } else if (!strcmp("open", av[1])) {
  179. int i, cnt = 0;
  180. BENCHO(create_open_close_q(++cnt), create_close_q(++cnt), REAL_SHORT);
  181. micro("message queue open latency", get_n());
  182. for (i = 1 ; i <= cnt ; i++)
  183. close_q(open_q(i));
  184. } else if (!strcmp("fork-open", av[1])) {
  185. int pipes[4];
  186. if (pipe(pipes) < 0 || pipe(pipes + 2) < 0) {
  187. perror("pipe");
  188. exit(1);
  189. }
  190. if (fork() == 0) {
  191. close(pipes[0]); close(pipes[3]); pipes[0] = pipes[2];
  192. int i, cnt = 0;
  193. BENCHO(client_create_open_q(pipes, ++cnt),
  194. client_create_q(pipes, ++cnt), REAL_SHORT);
  195. micro("message queue open latency after fork",
  196. get_n());
  197. exit(0);
  198. }
  199. close(pipes[1]); close(pipes[2]); pipes[1] = pipes[3];
  200. create_server(pipes);
  201. } else if (!strcmp("send", av[1])) {
  202. int id = create_q(0);
  203. int cnt = 0;
  204. BENCH(send_q(&id, ++cnt), REAL_SHORT);
  205. micro("message queue sending latency", get_n());
  206. close_q(id);
  207. } else if (!strcmp("fork-send", av[1])) {
  208. int id = create_q(0);
  209. int cnt = 0;
  210. if (fork() == 0) {
  211. BENCH(send_q(&id, ++cnt), REAL_SHORT);
  212. micro("message queue sending latency after fork",
  213. get_n());
  214. close_q(id);
  215. exit(0);
  216. }
  217. wait(NULL);
  218. } else if (!strcmp("receive", av[1])) {
  219. int id = create_q(0);
  220. int cnt = 0;
  221. BENCHO(send_receive_q(&id, ++cnt), send_q(&id, ++cnt), REAL_SHORT);
  222. micro("message queue receiving latency", get_n());
  223. close_q(id);
  224. } else if (!strcmp("fork-receive", av[1])) {
  225. int id = create_q(0);
  226. int cnt = 0;
  227. int pipes[4];
  228. if (pipe(pipes) < 0 || pipe(pipes + 2) < 0) {
  229. perror("pipe");
  230. exit(1);
  231. }
  232. if (fork() == 0) {
  233. close(pipes[0]); close(pipes[3]); pipes[0] = pipes[2];
  234. BENCHO(client_send_receive_q(pipes, ++cnt),
  235. client_send_q(pipes, ++cnt), REAL_SHORT);
  236. micro("message queue receiving latency after fork",
  237. get_n());
  238. exit(0);
  239. }
  240. close(pipes[1]); close(pipes[2]); pipes[1] = pipes[3];
  241. send_server(pipes, &id);
  242. close_q(id);
  243. } else {
  244. usage: printf("Usage: %s create|fork-create|open|fork-open"
  245. "|send|fork-send|receive|fork-receive\n", av[0]);
  246. }
  247. return(0);
  248. }