Add IPC benchmark 20/264420/11 submit/tizen/20211108.062031
authorUnsung Lee <unsung.lee@samsung.com>
Fri, 17 Sep 2021 08:18:15 +0000 (17:18 +0900)
committerUnsung Lee <unsung.lee@samsung.com>
Thu, 30 Sep 2021 10:49:21 +0000 (19:49 +0900)
Change-Id: Ia886f1d1d123185205d04f15efcc60deeb9909b6
Signed-off-by: Unsung Lee <unsung.lee@samsung.com>
Add IPC benchmark

Change-Id: Ia886f1d1d123185205d04f15efcc60deeb9909b6
Signed-off-by: Unsung Lee <unsung.lee@samsung.com>
Signed-off-by: Hyotaek Shim <hyotaek.shim@samsung.com>
Signed-off-by: Unsung Lee <unsung.lee@samsung.com>
Makefile
benchmark/common.c [new file with mode: 0644]
benchmark/common.h [new file with mode: 0644]
benchmark/gdbus.c [new file with mode: 0644]
benchmark/libdbus.c [new file with mode: 0644]
benchmark/pipe.c [new file with mode: 0644]
benchmark/sharedmem.c [new file with mode: 0644]
benchmark/socket.c [new file with mode: 0644]
benchmark/test_pc.sh [new file with mode: 0755]
benchmark/test_target.sh [new file with mode: 0755]
packaging/dbus-tools.spec

index a0040690fd8a4d715ddb24832c999671da686974..62def2e52faa8b6b68bff0e2964cc11e4017cf4b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1,24 @@
+CFLAGS= -D_GNU_SOURCE
+CFLAGS+= -I/usr/include/dlog -I/usr/lib/glib-2.0/include -I/usr/include/glib-2.0
+CFLAGS+= -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -L/usr/lib
+CFLAGS+=-Wall -O2 -g
+LDFLAGS= -lglib-2.0 -lgobject-2.0 -lgio-2.0 -lgmodule-2.0 -ldbus-1 -lgthread-2.0 -lpthread -lrt -lpcre
+LDFLAGS+=-lm
+DFTSRC=benchmark/common.c
+
+all:
+       gcc $(CFLAGS) -pg -o benchmark/pipe $(DFTSRC) benchmark/pipe.c $(LDFLAGS)
+       gcc $(CFLAGS) -o benchmark/socket $(DFTSRC) benchmark/socket.c $(LDFLAGS)
+       gcc $(CFLAGS) -o benchmark/sharedmem $(DFTSRC) benchmark/sharedmem.c $(LDFLAGS)
+       gcc $(CFLAGS) -o benchmark/gdbus $(DFTSRC) benchmark/gdbus.c $(LDFLAGS)
+       gcc $(CFLAGS) -o benchmark/libdbus $(DFTSRC) benchmark/libdbus.c $(LDFLAGS)
+
+
 install:
        make -C policychecker install
+       mkdir -p $(DESTDIR)/usr/bin
+       cp benchmark/pipe $(DESTDIR)/usr/bin/pipe
+       cp benchmark/socket $(DESTDIR)/usr/bin/socket
+       cp benchmark/sharedmem $(DESTDIR)/usr/bin/sharedmem
+       cp benchmark/gdbus $(DESTDIR)/usr/bin/gdbus
+       cp benchmark/libdbus $(DESTDIR)/usr/bin/libdbus
diff --git a/benchmark/common.c b/benchmark/common.c
new file mode 100644 (file)
index 0000000..d8d5cee
--- /dev/null
@@ -0,0 +1,26 @@
+#include "common.h"
+
+int cpu_pin(int cpuid, int pid) {
+       int ncpu = get_nprocs();
+       cpu_set_t set;
+
+       cpuid %= ncpu;
+
+       CPU_ZERO(&set);
+       CPU_SET(cpuid, &set);
+
+       if(sched_setaffinity(pid, sizeof(set), &set) == -1)
+               return 0;
+       else
+               return 1;
+}
+
+void print_help(char **argv)
+{
+       printf("%s [-m <message size>] [-p <#process>] [-b] [-l] [-h]\n", argv[0]);
+       printf("-m: message size\n");
+       printf("-p: the number of process (default: the number of CPU)\n");
+       printf("-b: measure bandwidth\n");
+       printf("-l: measure latency\n");
+       printf("-h: print help page\n");
+}
diff --git a/benchmark/common.h b/benchmark/common.h
new file mode 100644 (file)
index 0000000..f55c3a7
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef        BENCHMARK_COMMON
+#define BENCHMARK_COMMON
+
+#include <fcntl.h>
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sched.h>
+#include <sys/sysinfo.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/mman.h>
+
+#define        WARMUP_TRY      100
+#define        REAL_TRY        1000
+
+#define US                     1000000
+#define NS                     1000000000
+
+#define        ONE_PAGE_SIZE   4096
+
+typedef        enum {false, true}      bool;
+void print_help(char **argv);
+int cpu_pin(int cpuid, int pid);
+
+#endif
diff --git a/benchmark/gdbus.c b/benchmark/gdbus.c
new file mode 100644 (file)
index 0000000..8f05062
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * lat_gdbus.c - gdbus IPC latency
+ *
+ */
+
+#include <gio/gio.h>
+#include "common.h"
+
+typedef struct _state {
+       int iters;
+       char *buf;
+       bool is_lt;
+       GMainLoop *main_loop;
+} State;
+
+int nprocs;
+int msize;
+int lt_cnt;
+double min, max, total;
+unsigned long long bw;
+
+bool lt_on, bw_on;
+
+static void server_name_acquired_handler (GDBusConnection *conn, const gchar *name, gpointer user_data)
+{ }
+
+static void server_name_lost_handler (GDBusConnection *conn, const gchar *name, gpointer user_data)
+{ }
+
+static GVariant *handle_get_property (GDBusConnection *connection,
+               const gchar           *sender,
+               const gchar           *object_path,
+               const gchar           *interface_name,
+               const gchar           *property_name,
+               GError                **error,
+               gpointer              user_data)
+{ }
+
+static gboolean handle_set_property (GDBusConnection *connection,
+               const gchar           *sender,
+               const gchar           *object_path,
+               const gchar           *interface_name,
+               const gchar           *property_name,
+               GVariant              *value,
+               GError                **error,
+               gpointer              user_data)
+{ }
+
+static void handle_method_call (GDBusConnection       *connection,
+               const gchar           *sender,
+               const gchar           *object_path,
+               const gchar           *interface_name,
+               const gchar           *method_name,
+               GVariant              *parameters,
+               GDBusMethodInvocation *invocation,
+               gpointer              user_data)
+{
+       static int bw_cnt = 0;
+       static int cnt = 0;
+       static unsigned long long start;
+       unsigned long long end;
+       unsigned long long temp;
+       struct timespec clock;
+       State *state = (State *)user_data;
+
+       if (g_strcmp0 (method_name, "Perf") == 0)
+       {
+               if(state->is_lt)
+                       g_variant_get (parameters, "(ts)", &start, &state->buf);
+               else
+                       g_variant_get (parameters, "(ts)", &temp, &state->buf);
+
+               g_object_unref (invocation);
+
+               if(++cnt == state->iters) {cnt = 0; g_main_loop_quit (state->main_loop); }
+
+               if(state->buf[0] != 'r')
+                       return;
+
+               if(state->is_lt) {
+                       clock_gettime (CLOCK_REALTIME, &clock);
+                       end = (unsigned long long)clock.tv_sec * NS
+                               +(unsigned long long)clock.tv_nsec;
+
+                       double lt = (double)(end - start) / 1000;
+#ifdef DEBUG_ON
+                       printf("latency: %0.4f\n", lt);
+#endif
+
+                       if(lt > 0) {
+                               lt_cnt++;
+                               total += lt;
+                               if(lt > max)
+                                       max = lt;
+
+                               if(lt < min)
+                                       min = lt;
+                       }
+               }
+               else {
+                       bw_cnt++;
+                       if(bw_cnt == 1) {
+                               clock_gettime (CLOCK_REALTIME, &clock);
+                               start = (unsigned long long)clock.tv_sec * NS
+                                       + (unsigned long long)clock.tv_nsec;
+                       }
+
+                       if(bw_cnt == REAL_TRY) {
+                               clock_gettime (CLOCK_REALTIME, &clock);
+                               end = (unsigned long long)clock.tv_sec * NS
+                                       +(unsigned long long)clock.tv_nsec;
+                               bw = ((unsigned long long)NS * bw_cnt)/(end - start);
+                               printf("bandwidth: %llu (/s)\n", bw);
+                       }
+               }
+       }
+}
+
+static const GDBusInterfaceVTable _vtable =
+{
+       handle_method_call,
+       handle_get_property,
+       handle_set_property
+};
+
+void Receive(register int size, const char *name, const char *path, bool is_lt)
+{
+       State state;
+       register char *buf = (char *)malloc(size);
+
+       GMainLoop *g_main_loop = g_main_loop_new (g_main_context_default(), FALSE);
+       GDBusConnection *conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+       g_assert(conn != NULL);
+       guint id = g_bus_own_name_on_connection (conn, name, G_BUS_NAME_OWNER_FLAGS_NONE
+                       , server_name_acquired_handler
+                       , server_name_lost_handler
+                       , NULL, NULL);
+       g_assert(id != 0);
+
+       static gchar _interface_introspection_xml[5000];
+       sprintf(_interface_introspection_xml,
+               "<node>"
+               "       <interface name='%s'>"
+               "               <method name='Perf'>"
+               "                       <arg type='t' name='Start' direction='in'/>"
+               "                       <arg type='s' name='Msg' direction='in'/>"
+               "                       <arg type='t' name='Response' direction='out'/>"
+               "               </method>"
+               "       </interface>"
+               "</node>", name);
+
+       GDBusNodeInfo *introspection_data = NULL;
+       introspection_data = g_dbus_node_info_new_for_xml (_interface_introspection_xml, NULL);
+
+       state.iters = WARMUP_TRY + REAL_TRY;
+       state.is_lt = is_lt;
+       state.buf = buf;
+       state.main_loop = g_main_loop;
+
+       guint rid = g_dbus_connection_register_object (conn, path
+                       , introspection_data->interfaces[0]
+                       , &_vtable
+                       , (gpointer)&state, NULL, NULL);
+       g_assert(rid > 0);
+
+
+
+       g_main_loop_run (g_main_loop);
+
+       g_dbus_connection_unregister_object(conn, rid);
+       g_bus_unown_name (id);
+       g_dbus_connection_close(conn, NULL, NULL, NULL);
+       g_object_unref(conn);
+       free(buf);
+}
+
+void Send(register int size, const char *name, const char *path, bool is_lt)
+{
+       unsigned long long start;
+       register char *cptr = (char *)malloc(size);
+       GDBusConnection *conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+       g_assert(conn != NULL);
+
+       sleep(2);
+       for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+               struct timespec clock;
+
+               memset(cptr, 0, size);
+               if(i >= WARMUP_TRY)
+                       cptr[0] = 'r';
+               else
+                       cptr[0] = 'w';
+
+               if(is_lt) {
+                       clock_gettime (CLOCK_REALTIME, &clock);
+                       start = (unsigned long long)clock.tv_sec * NS
+                               +(unsigned long long)clock.tv_nsec;
+               }
+               else
+                       start = 0;
+
+               //GError *error = NULL;
+               g_dbus_connection_call(conn,
+                               name,
+                               path,
+                               name,
+                               "Perf",
+                               g_variant_new ("(ts)", start, cptr),
+                               NULL,
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1,
+                               NULL,
+                               NULL,
+                               NULL);
+               /*if(error != NULL) {
+                 g_printerr("Error=%s\n", error->message);
+                               g_error_free (error);
+                       }*/
+               if(is_lt) {
+                       if(size <= ONE_PAGE_SIZE)
+                               usleep(5000);
+                       else if(size <= 10 * ONE_PAGE_SIZE)
+                               usleep(10000);
+                       else if(size <= 100 * ONE_PAGE_SIZE)
+                               usleep(20000);
+                       else
+                               usleep(40000);
+               }
+       }
+
+       g_dbus_connection_close(conn, NULL, NULL, NULL);
+       g_object_unref(conn);
+       free(cptr);
+}
+
+void Measure_bandwidth(void)
+{
+       int ret;
+       int returnp[nprocs/2][2];
+       int pids[nprocs];
+       int ready_fd;
+       char *ready_ptr;
+
+       ready_fd = shm_open("isready", O_CREAT | O_TRUNC | O_RDWR, 0666);
+       if(ready_fd == -1)
+       {
+               perror("Open");
+               return;
+       }
+       if(ftruncate(ready_fd, sizeof(char))) {
+               perror("Ftruncate");
+               return;
+       }
+       ready_ptr = mmap(0, sizeof(char), PROT_READ | PROT_WRITE,
+                       MAP_SHARED, ready_fd, 0);
+       if(ready_ptr == MAP_FAILED) {
+               perror("Mmap");
+               return;
+       }
+       close(ready_fd);
+       ready_ptr[0] = 'n';
+
+       for(int i = 0; i < nprocs/2; i++) {
+               if(pipe(returnp[i]) == -1) {
+                       perror("pipe");
+                       exit(1);
+               }
+       }
+
+       if(!cpu_pin(0, getpid())) {
+               perror("CPU pinning for parent");
+               exit(1);
+       }
+
+       for(int child = 1; child < nprocs; child++) {
+               char name[30];
+               char path[30];
+
+               sprintf(name, "org.gdbus.server%d", child/2);
+               sprintf(path, "/org/gdbus/server%d", child/2);
+               int pid = fork();
+               switch (pid) {
+                       //child
+                       case 0:
+                               if(!cpu_pin(child, getpid())) {
+                                       perror("CPU pinning for child");
+                                       exit(1);
+                               }
+
+                               // Wait for parent
+                               while(ready_ptr[0] == 'n') {
+                               }
+
+                               if(child % 2 == 0) {
+                                       Receive(msize, (const char *)name, (const char *)path, false);
+
+                                       //send result(bandwidth) to parent
+                                       {
+                                               int wres;
+                                               close(returnp[child/2][0]);
+                                               wres = write(returnp[child/2][1], (void *)&bw, sizeof(unsigned long long));
+                                               if (wres != sizeof(unsigned long long)) {
+                                                       perror("(write return) read/write on pipe sender");
+                                                       exit(1);
+                                               }
+                                               close(returnp[child/2][1]);
+                                       }
+                               }
+                               else {
+                                       Send(msize, (const char *)name, (const char *)path, false);
+                               }
+
+                               exit(0);
+                       case -1:
+                               perror("fork");
+                               return;
+                       default:
+                               pids[child] = pid;
+                               break;
+               }
+       }
+
+       sleep(1);
+       ready_ptr[0] = 'y';
+
+       Receive(msize, "org.gdbus.server0", "/org/gdbus/server0", false);
+       for(int child = 1; child < nprocs; child++) {
+               //receive result(bandwidth) from child(s)
+               if(child % 2 == 0) {
+                       int rres;
+                       unsigned long long child_bw;
+
+                       close(returnp[child/2][1]);
+                       rres = read(returnp[child/2][0], (void *)&child_bw, sizeof(unsigned long long));
+                       if (rres != sizeof(unsigned long long)) {
+                               perror("(write return) read/write on pipe receiver");
+                               exit(1);
+                       }
+                       close(returnp[child/2][0]);
+                       bw += child_bw;
+               }
+
+               waitpid(pids[child], NULL, 0);
+       }
+       ret = munmap(ready_ptr, sizeof(bool));
+       if (ret != 0) {
+               perror("munmap");
+               exit(1);
+       }
+
+       ret = shm_unlink("isready");
+       if (ret != 0) {
+               perror("shm unlink");
+               //exit(1);
+       }
+       printf("Total bandwidth: %llu (/s)\n", bw);
+}
+
+
+void Measure_latency(void)
+{
+       if(!cpu_pin(0, getpid())) {
+               perror("CPU pinning for parent");
+               exit(1);
+       }
+
+       int pid = fork();
+       switch (pid) {
+               //child
+               case 0:
+                       if(!cpu_pin(1, getpid())) {
+                               perror("CPU pinning for child");
+                               exit(1);
+                       }
+
+                       Send(msize, "org.gdbus.server", "/org/gdbus/server", true);
+
+                       exit(0);
+               case -1:
+                       perror("fork");
+                       return;
+               default:
+                       Receive(msize, "org.gdbus.server", "/org/gdbus/server", true);
+                       printf("min: %0.4f(us), max: %0.4f(us), avg: %0.4f(us)\n", min, max, total/lt_cnt);
+
+                       waitpid(pid, NULL, 0);
+                       return;
+       }
+}
+
+       int
+main(int argc, char **argv)
+{
+       int opt;
+       extern char *optarg;
+       extern int optind;
+
+       nprocs = get_nprocs();
+       if(nprocs == 1)
+               nprocs = 2;
+
+       msize = 3;
+       lt_on = bw_on = false;
+       while((opt = getopt(argc, argv, "m:p:blh")) != -1) {
+               switch(opt) {
+               case 'm':
+                       msize = atoi(optarg);
+                       break;
+               case 'p':
+                       nprocs = atoi(optarg);
+                       if(nprocs <= 0) {
+                               printf("The number of process should be larger than 0\n");
+                               exit(0);
+                       }
+                       if(nprocs % 2 != 0) {
+                               printf("The number of process should be even\n");
+                               exit(0);
+                       }
+                       break;
+               case 'b':
+                       bw_on = true;
+                       break;
+               case 'l':
+                       lt_on = true;
+                       break;
+               case 'h':
+                       print_help(argv);
+                       exit(0);
+               }
+       }
+
+       if(!lt_on && !bw_on) {
+               print_help(argv);
+               exit(0);
+       }
+
+       bw = 0;
+       lt_cnt = 0;
+       max = total = 0.0;
+       min = 1000000.0;
+
+       if(lt_on)
+               Measure_latency();
+
+       if(bw_on)
+               Measure_bandwidth();
+}
diff --git a/benchmark/libdbus.c b/benchmark/libdbus.c
new file mode 100644 (file)
index 0000000..2beea9d
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * lat_libdbus.c - libdbus IPC latency
+ *
+ */
+
+#include <dbus/dbus.h>
+#include "common.h"
+
+typedef struct _state {
+       int iters;
+       char *buf;
+       bool is_lt;
+} State;
+
+int nprocs;
+int msize;
+int lt_cnt;
+double min, max, total;
+unsigned long long bw;
+
+bool lt_on, bw_on;
+bool stop;
+
+static void unregistered_func (DBusConnection *connection, void *user_data)
+{ }
+
+static DBusHandlerResult message_func (DBusConnection *connection,
+                                           DBusMessage *message,
+                                           void *user_data)
+{
+       static int bw_cnt = 0;
+       static int cnt = 0;
+       static unsigned long long start;
+       unsigned long long end;
+       unsigned long long temp;
+       struct timespec clock;
+       State *state = (State *)user_data;
+
+       //if (dbus_message_is_method_call (message, "org.libdbus.server", "Perf"))
+       {
+               if(state->is_lt)
+                       dbus_message_get_args (message, NULL, DBUS_TYPE_UINT64, &start,
+                                       DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &state->buf, &msize, DBUS_TYPE_INVALID);
+               else
+                       dbus_message_get_args (message, NULL, DBUS_TYPE_UINT64, &temp,
+                                       DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &state->buf, &msize, DBUS_TYPE_INVALID);
+
+               if(++cnt == state->iters) {cnt = 0; stop = true; }
+
+               if(state->buf[0] != 'r')
+                       return DBUS_HANDLER_RESULT_HANDLED;
+
+               if(state->is_lt) {
+                       clock_gettime (CLOCK_REALTIME, &clock);
+                       end = (unsigned long long)clock.tv_sec * NS
+                               +(unsigned long long)clock.tv_nsec;
+
+                       double lt = (double)(end - start) / 1000;
+
+                       if(lt) {
+                               lt_cnt++;
+                               total += lt;
+                               if(lt > max)
+                                       max = lt;
+
+                               if(lt < min)
+                                       min = lt;
+                       }
+               }
+               else {
+                       bw_cnt++;
+                       if(bw_cnt == 1) {
+                               clock_gettime (CLOCK_REALTIME, &clock);
+                               start = (unsigned long long)clock.tv_sec * NS
+                                       + (unsigned long long)clock.tv_nsec;
+                       }
+
+                       if(bw_cnt == REAL_TRY) {
+                               clock_gettime (CLOCK_REALTIME, &clock);
+                               end = (unsigned long long)clock.tv_sec * NS
+                                       +(unsigned long long)clock.tv_nsec;
+                               bw = ((unsigned long long)NS * bw_cnt)/(end - start);
+                               printf("bandwidth: %llu (/s)\n", bw);
+                       }
+               }
+       }
+       return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusObjectPathVTable vtable = {
+       unregistered_func,
+       message_func,
+       NULL,
+};
+
+
+void Receive(register int size, const char *name, const char *path, bool is_lt)
+{
+       State state;
+       DBusError error;
+       DBusConnection* conn;
+       char *buf = (char *)malloc(size);
+
+       dbus_error_init(&error);
+       conn = dbus_bus_get_private(DBUS_BUS_SESSION, &error);
+       if (dbus_error_is_set (&error)) {
+               dbus_error_free (&error);
+               exit(1);
+       }
+
+       int ret = dbus_bus_request_name (conn, name,
+                       DBUS_NAME_FLAG_REPLACE_EXISTING|DBUS_NAME_FLAG_DO_NOT_QUEUE, NULL);
+       if( ret == -1 ) {
+               perror("dbus_bus_request_name()\n");
+               exit(1);
+       }
+
+       state.iters = WARMUP_TRY + REAL_TRY;
+       state.is_lt = is_lt;
+       state.buf = buf;
+       dbus_connection_register_object_path (conn, path, &vtable, &state);
+
+       //for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+       while(1) {
+               if(!dbus_connection_read_write_dispatch(conn, -1)) {
+                       printf("read on parent error\n");
+                       exit(1);
+               }
+
+               if(stop)
+                       break;
+       }
+       stop = false;
+       //}
+
+       dbus_connection_unregister_object_path (conn, path);
+       free(buf);
+}
+
+void Send(register int size, const char *name, const char *path, const char *client, bool is_lt)
+{
+       DBusMessage *msg;
+       unsigned long long start;
+
+       char *cptr = (char *)malloc(size);
+       DBusConnection* conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+       int ret = dbus_bus_request_name (conn, client, DBUS_NAME_FLAG_REPLACE_EXISTING, NULL);
+       if( ret == -1 ) {
+               perror("dbus_bus_request_name()\n");
+               exit(1);
+       }
+
+       sleep(2);
+       for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+               struct timespec clock;
+
+               memset(cptr, 0, size);
+               if(i >= WARMUP_TRY)
+                       cptr[0] = 'r';
+               else
+                       cptr[0] = 'w';
+
+               if(is_lt) {
+                       clock_gettime (CLOCK_REALTIME, &clock);
+                       start = (unsigned long long)clock.tv_sec * NS
+                               +(unsigned long long)clock.tv_nsec;
+               }
+               else
+                       start = 0;
+
+               msg = dbus_message_new_method_call (name, path, name, "Perf");
+               DBusMessageIter iter;
+               dbus_message_iter_init_append (msg, &iter);
+               dbus_message_append_args (msg,
+                               DBUS_TYPE_UINT64, &start,
+                               DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &cptr, size,
+                               DBUS_TYPE_INVALID);
+               dbus_message_set_no_reply(msg, 1);
+               dbus_connection_send (conn, msg, NULL);
+
+               if(is_lt) {
+                       if(size <= ONE_PAGE_SIZE)
+                               usleep(5000);
+                       else if(size <= 10 * ONE_PAGE_SIZE)
+                               usleep(10000);
+                       else if(size <= 100 * ONE_PAGE_SIZE)
+                               usleep(20000);
+                       else
+                               usleep(40000);
+               }
+       }
+
+       dbus_connection_flush(conn);
+       dbus_message_unref (msg);
+       free(cptr);
+}
+
+void Measure_bandwidth(void)
+{
+       int ret;
+       int returnp[nprocs/2][2];
+       int pids[nprocs];
+       int ready_fd;
+       char *ready_ptr;
+
+       ready_fd = shm_open("isready", O_CREAT | O_TRUNC | O_RDWR, 0666);
+       if(ready_fd == -1)
+       {
+               perror("Open");
+               return;
+       }
+       if(ftruncate(ready_fd, sizeof(char))) {
+               perror("Ftruncate");
+               return;
+       }
+       ready_ptr = mmap(0, sizeof(char), PROT_READ | PROT_WRITE,
+                       MAP_SHARED, ready_fd, 0);
+       if(ready_ptr == MAP_FAILED) {
+               perror("Mmap");
+               return;
+       }
+       close(ready_fd);
+       ready_ptr[0] = 'n';
+
+       for(int i = 0; i < nprocs/2; i++) {
+               if(pipe(returnp[i]) == -1) {
+                       perror("pipe");
+                       exit(1);
+               }
+       }
+
+       if(!cpu_pin(0, getpid())) {
+               perror("CPU pinning for parent");
+               exit(1);
+       }
+
+       for(int child = 1; child < nprocs; child++) {
+               char name[30];
+               char path[30];
+
+               sprintf(name, "org.libdbus.server%d", child/2);
+               sprintf(path, "/org/libdbus/server%d", child/2);
+               int pid = fork();
+               switch (pid) {
+                       //child
+                       case 0:
+                               if(!cpu_pin(child, getpid())) {
+                                       perror("CPU pinning for child");
+                                       exit(1);
+                               }
+
+                               // Wait for parent
+                               while(ready_ptr[0] == 'n') {
+                               }
+
+                               if(child % 2 == 0) {
+                                       Receive(msize, (const char *)name, (const char *)path, false);
+
+                                       //send result(bandwidth) to parent
+                                       {
+                                               int wres;
+                                               close(returnp[child/2][0]);
+                                               wres = write(returnp[child/2][1], (void *)&bw, sizeof(unsigned long long));
+                                               if (wres != sizeof(unsigned long long)) {
+                                                       perror("(write return) read/write on pipe sender");
+                                                       exit(1);
+                                               }
+                                               close(returnp[child/2][1]);
+                                       }
+                               }
+                               else {
+                                       char client[30];
+                                       sprintf(client, "org.libdbus.client%d", child);
+                                       Send(msize, (const char *)name, (const char *)path, (const char *)client, false);
+                               }
+
+                               exit(0);
+                       case -1:
+                               perror("fork");
+                               return;
+                       default:
+                               pids[child] = pid;
+                               break;
+               }
+       }
+
+       sleep(1);
+       ready_ptr[0] = 'y';
+
+       Receive(msize, "org.libdbus.server0", "/org/libdbus/server0", false);
+       for(int child = 1; child < nprocs; child++) {
+               //receive result(bandwidth) from child(s)
+               if(child % 2 == 0) {
+                       int rres;
+                       unsigned long long child_bw;
+
+                       close(returnp[child/2][1]);
+                       rres = read(returnp[child/2][0], (void *)&child_bw, sizeof(unsigned long long));
+                       if (rres != sizeof(unsigned long long)) {
+                               perror("(write return) read/write on pipe receiver");
+                               exit(1);
+                       }
+                       close(returnp[child/2][0]);
+                       bw += child_bw;
+               }
+
+               waitpid(pids[child], NULL, 0);
+       }
+       ret = munmap(ready_ptr, sizeof(bool));
+       if (ret != 0) {
+               perror("munmap");
+               exit(1);
+       }
+
+       ret = shm_unlink("isready");
+       if (ret != 0) {
+               perror("shm unlink");
+               //exit(1);
+       }
+       printf("Total bandwidth: %llu (/s)\n", bw);
+}
+
+void Measure_latency(void)
+{
+       if(!cpu_pin(0, getpid())) {
+               perror("CPU pinning for parent");
+               exit(1);
+       }
+
+       int pid = fork();
+       switch (pid) {
+               //child
+               case 0:
+                       if(!cpu_pin(1, getpid())) {
+                               perror("CPU pinning for child");
+                               exit(1);
+                       }
+
+                       Send(msize, "org.libdbus.server", "/org/libdbus/server", "org.libdbus.client", true);
+
+                       exit(0);
+               case -1:
+                       perror("fork");
+                       return;
+               default:
+                       Receive(msize, "org.libdbus.server", "/org/libdbus/server", true);
+                       printf("min: %0.4f(us), max: %0.4f(us), avg: %0.4f(us)\n", min, max, total/lt_cnt);
+                       waitpid(pid, NULL, 0);
+                       return;
+       }
+}
+
+       int
+main(int argc, char **argv)
+{
+       int opt;
+       extern char *optarg;
+       extern int optind;
+
+       nprocs = get_nprocs();
+       if(nprocs == 1)
+               nprocs = 2;
+
+       msize = 3;
+       lt_on = bw_on = false;
+       while((opt = getopt(argc, argv, "m:p:blh")) != -1) {
+               switch(opt) {
+               case 'm':
+                       msize = atoi(optarg);
+                       break;
+               case 'p':
+                       nprocs = atoi(optarg);
+                       if(nprocs <= 0) {
+                               printf("The number of process should be larger than 0\n");
+                               exit(0);
+                       }
+                       if(nprocs % 2 != 0) {
+                               printf("The number of process should be even\n");
+                               exit(0);
+                       }
+                       break;
+               case 'b':
+                       bw_on = true;
+                       break;
+               case 'l':
+                       lt_on = true;
+                       break;
+               case 'h':
+                       print_help(argv);
+                       exit(0);
+               }
+       }
+
+       if(!lt_on && !bw_on) {
+               print_help(argv);
+               exit(0);
+       }
+
+       bw = 0;
+       lt_cnt = 0;
+       max = total = 0.0;
+       min = 1000000.0;
+
+       if(lt_on)
+               Measure_latency();
+
+       if(bw_on)
+               Measure_bandwidth();
+}
diff --git a/benchmark/pipe.c b/benchmark/pipe.c
new file mode 100644 (file)
index 0000000..9993a28
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * lat_pipe.c - pipe IPC latency
+ *
+ */
+
+#include "common.h"
+
+int nprocs;
+int msize;
+int lt_cnt;
+double min, max, total;
+unsigned long long bw;
+
+bool lt_on, bw_on;
+
+void Receive(int rfd1, int rfd2, register int size, bool is_lt)
+{
+       static int bw_cnt = 0;
+       unsigned long long start;
+       unsigned long long end;
+       register char *buf = (char *)malloc(size);
+
+       for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+               if(is_lt) {
+                       if (read(rfd1, (void *)&start, sizeof(unsigned long long))
+                               != sizeof(unsigned long long)) {
+                               perror("(read 1) read/write on pipe receiver");
+                               exit(1);
+                       }
+               }
+
+               if (read(rfd2, buf, size) != size) {
+                       perror("(read 2) read/write on pipe receiver");
+                       exit(1);
+               }
+               else if(buf[0] == 'r') {
+                       struct timespec clock;
+                       if(is_lt) {
+                               clock_gettime (CLOCK_REALTIME, &clock);
+                               end = (unsigned long long)clock.tv_sec * NS
+                                       +(unsigned long long)clock.tv_nsec;
+
+                               double lt = (double)(end - start) / 1000;
+#ifdef DEBUG_ON
+                               printf("latency: %0.4f\n", lt);
+#endif
+
+                               if(lt > 0) {
+                                       lt_cnt++;
+                                       total += lt;
+                                       if(lt > max)
+                                               max = lt;
+
+                                       if(lt < min)
+                                               min = lt;
+                               }
+                       }
+                       else {
+                               bw_cnt++;
+                               if(bw_cnt == 1) {
+                                       clock_gettime (CLOCK_REALTIME, &clock);
+                                       start = (unsigned long long)clock.tv_sec * NS
+                                               + (unsigned long long)clock.tv_nsec;
+                               }
+
+                               if(bw_cnt == REAL_TRY) {
+                                       clock_gettime (CLOCK_REALTIME, &clock);
+                                       end = (unsigned long long)clock.tv_sec * NS
+                                               +(unsigned long long)clock.tv_nsec;
+                                       bw = ((unsigned long long)NS * bw_cnt)/(end - start);
+                                       printf("bandwidth: %llu (/s)\n", bw);
+                               }
+                       }
+               }
+       }
+
+       free(buf);
+}
+
+void Send(int wfd1, int wfd2, register int size, bool is_lt)
+{
+       register char *cptr = (char *)malloc(size);
+
+       sleep(2);
+       for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+               int wres1, wres2;
+               struct timespec clock;
+
+               memset(cptr, 0, size);
+               if(i >= WARMUP_TRY)
+                       cptr[0] = 'r';
+               else
+                       cptr[0] = 'w';
+
+               if(is_lt) {
+                       clock_gettime (CLOCK_REALTIME, &clock);
+                       unsigned long long start = (unsigned long long)clock.tv_sec * NS
+                               +(unsigned long long)clock.tv_nsec;
+
+                       wres1 = write(wfd1, (void *)&start, sizeof(unsigned long long));
+                       if (wres1 != sizeof(unsigned long long)) {
+                               perror("(write 1) read/write on pipe sender");
+                               exit(1);
+                       }
+               }
+               wres2 = write(wfd2, cptr, size);
+               if (wres2 != size) {
+                       perror("(write 2) read/write on pipe sender");
+                       exit(1);
+               }
+
+               if(is_lt) {
+                       if(size <= ONE_PAGE_SIZE)
+                               usleep(5000);
+                       else if(size <= 10 * ONE_PAGE_SIZE)
+                               usleep(10000);
+                       else if(size <= 100 * ONE_PAGE_SIZE)
+                               usleep(20000);
+                       else
+                               usleep(40000);
+               }
+       }
+
+       free(cptr);
+}
+
+void Measure_bandwidth(void)
+{
+       int ret;
+       int returnp[nprocs/2][2];
+       int p[nprocs/2][2];
+       int pids[nprocs];
+       int ready_fd;
+       char *ready_ptr;
+
+       ready_fd = shm_open("isready", O_CREAT | O_TRUNC | O_RDWR, 0666);
+       if(ready_fd == -1)
+       {
+               perror("Open");
+               return;
+       }
+       if(ftruncate(ready_fd, sizeof(char))) {
+               perror("Ftruncate");
+               return;
+       }
+       ready_ptr = mmap(0, sizeof(char), PROT_READ | PROT_WRITE,
+                       MAP_SHARED, ready_fd, 0);
+       if(ready_ptr == MAP_FAILED) {
+               perror("Mmap");
+               return;
+       }
+       close(ready_fd);
+       ready_ptr[0] = "n";
+
+       for(int i = 0; i < nprocs/2; i++) {
+               if(pipe(returnp[i]) == -1) {
+                       perror("pipe");
+                       exit(1);
+               }
+       }
+
+       for(int i = 0; i < nprocs/2; i++) {
+               if(pipe(p[i]) == -1) {
+                       perror("pipe");
+                       exit(1);
+               }
+       }
+
+       if(!cpu_pin(0, getpid())) {
+               perror("CPU pinning for parent");
+               exit(1);
+       }
+
+       for(int child = 1; child < nprocs; child++) {
+               int pid = fork();
+               switch (pid) {
+                       //child
+                       case 0:
+                               if(!cpu_pin(child, getpid())) {
+                                       perror("CPU pinning for child");
+                                       exit(1);
+                               }
+                               if(child % 2 == 0) {
+                                       close(p[child/2][1]);
+                               }
+                               else
+                                       close(p[child/2][0]);
+
+                               // Wait for parent
+                               while(ready_ptr[0] == "n") {
+                               }
+
+                               if(child % 2 == 0) {
+                                       Receive(0, p[child/2][0], msize, false);
+                                       close(p[child/2][0]);
+
+                                       //send result(bandwidth) to parent
+                                       {
+                                               int wres;
+                                               close(returnp[child/2][0]);
+                                               wres = write(returnp[child/2][1], (void *)&bw, sizeof(unsigned long long));
+                                               if (wres != sizeof(unsigned long long)) {
+                                                       perror("(write return) read/write on pipe sender");
+                                                       exit(1);
+                                               }
+                                               close(returnp[child/2][1]);
+                                       }
+                               }
+                               else {
+                                       Send(0, p[child/2][1], msize, false);
+                                       close(p[child/2][1]);
+                               }
+
+                               exit(0);
+                       case -1:
+                               perror("fork");
+                               return;
+                       default:
+                               pids[child] = pid;
+               }
+       }
+
+       usleep(100000);
+       close(p[0][1]);
+       ready_ptr[0] = "y";
+
+       Receive(0, p[0][0], msize, false);
+       close(p[0][0]);
+       for(int child = 1; child < nprocs; child++) {
+               //receive result(bandwidth) from child(s)
+               if(child % 2 == 0) {
+                       int rres;
+                       unsigned long long child_bw;
+
+                       close(returnp[child/2][1]);
+                       rres = read(returnp[child/2][0], (void *)&child_bw, sizeof(unsigned long long));
+                       if (rres != sizeof(unsigned long long)) {
+                               perror("(read return) read/write on pipe receiver");
+                               exit(1);
+                       }
+                       close(returnp[child/2][0]);
+                       bw += child_bw;
+               }
+
+               waitpid(pids[child], NULL, 0);
+       }
+
+       ret = munmap(ready_ptr, sizeof(bool));
+       if (ret != 0) {
+               perror("munmap");
+               exit(1);
+       }
+
+       ret = shm_unlink("isready");
+       if (ret != 0) {
+               perror("shm unlink");
+               //exit(1);
+       }
+       printf("Total bandwidth: %llu (/s)\n", bw);
+}
+
+void Measure_latency(void)
+{
+       int p1[2], p2[2];
+
+       if (pipe(p1) == -1) {
+               perror("pipe");
+               exit(1);
+       }
+       if (pipe(p2) == -1) {
+               perror("pipe");
+               exit(1);
+       }
+
+       if(!cpu_pin(0, getpid())) {
+               perror("CPU pinning for parent");
+               exit(1);
+       }
+
+       int pid = fork();
+       switch (pid) {
+               //child
+               case 0:
+                       if(!cpu_pin(1, getpid())) {
+                               perror("CPU pinning for child");
+                               exit(1);
+                       }
+                       close(p1[0]);
+                       close(p2[0]);
+                       Send(p1[1], p2[1], msize, true);
+                       close(p1[1]);
+                       close(p2[1]);
+                       exit(0);
+               case -1:
+                       perror("fork");
+                       return;
+               default:
+                       close(p1[1]);
+                       close(p2[1]);
+                       Receive(p1[0], p2[0], msize, true);
+                       close(p1[0]);
+                       close(p2[0]);
+                       printf("min: %0.4f(us), max: %0.4f(us), avg: %0.4f(us)\n", min, max, total/lt_cnt);
+                       waitpid(pid, NULL, 0);
+                       return;
+       }
+}
+
+       int
+main(int argc, char **argv)
+{
+       int opt;
+       extern char *optarg;
+       extern int optind;
+
+       nprocs = get_nprocs();
+       if(nprocs == 1)
+               nprocs = 2;
+
+       msize = 3;
+       lt_on = bw_on = false;
+       while((opt = getopt(argc, argv, "m:p:blh")) != -1) {
+               switch(opt) {
+               case 'm':
+                       msize = atoi(optarg);
+                       break;
+               case 'p':
+                       nprocs = atoi(optarg);
+                       if(nprocs <= 0) {
+                               printf("The number of process should be larger than 0\n");
+                               exit(0);
+                       }
+                       if(nprocs % 2 != 0) {
+                               printf("The number of process should be even\n");
+                               exit(0);
+                       }
+                       break;
+               case 'b':
+                       bw_on = true;
+                       break;
+               case 'l':
+                       lt_on = true;
+                       break;
+               case 'h':
+                       print_help(argv);
+                       exit(0);
+               }
+       }
+
+       if(!lt_on && !bw_on) {
+               print_help(argv);
+               exit(0);
+       }
+
+       bw = 0;
+       lt_cnt = 0;
+       max = total = 0.0;
+       min = 1000000.0;
+
+       if(lt_on)
+               Measure_latency();
+
+       if(bw_on)
+               Measure_bandwidth();
+}
diff --git a/benchmark/sharedmem.c b/benchmark/sharedmem.c
new file mode 100644 (file)
index 0000000..a1056e6
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * lat_sharedmem.c - sharedmem IPC latency
+ *
+ */
+
+#include "common.h"
+
+#define SHM1   0
+#define SHM2   1
+
+const char *shm_name1 = "sharedmem1";
+const char *shm_name2 = "sharedmem2";
+
+int nprocs;
+int msize;
+int lt_cnt;
+double min, max, total;
+unsigned long long bw;
+
+bool lt_on, bw_on;
+
+void Receive(void *r1, register char *r2, register int size, bool is_lt)
+{
+       static int bw_cnt = 0;
+       unsigned long long start;
+       unsigned long long end;
+       struct timespec clock;
+       register char read_cnt = 0;
+       register char *buf = (char *)malloc(size);
+
+       for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+repeat:
+               if(r2[1] == read_cnt)
+                       goto repeat;
+               else
+                       read_cnt = r2[1];
+
+               memcpy(buf, r2, size);
+               r2[2] = read_cnt;
+               if(buf[0] != 'r')
+                       continue;
+
+               if(is_lt) {
+                       memcpy((void *)&start, r1, sizeof(unsigned long long));
+                       clock_gettime (CLOCK_REALTIME, &clock);
+                       end = (unsigned long long)clock.tv_sec * NS
+                               +(unsigned long long)clock.tv_nsec;
+
+                       double lt = (double)(end - start) / 1000;
+#ifdef DEBUG_ON
+                       printf("latency: %0.4f\n", lt);
+#endif
+
+                       if(lt > 0) {
+                               lt_cnt++;
+                               total += lt;
+                               if(lt > max)
+                                       max = lt;
+
+                               if(lt < min)
+                                       min = lt;
+                       }
+               }
+               else {
+                       bw_cnt++;
+                       if(bw_cnt == 1) {
+                               clock_gettime (CLOCK_REALTIME, &clock);
+                               start = (unsigned long long)clock.tv_sec * NS
+                                       + (unsigned long long)clock.tv_nsec;
+                       }
+
+                       if(bw_cnt == REAL_TRY) {
+                               clock_gettime (CLOCK_REALTIME, &clock);
+                               end = (unsigned long long)clock.tv_sec * NS
+                                       +(unsigned long long)clock.tv_nsec;
+                               bw = ((unsigned long long)NS * bw_cnt)/(end - start);
+                               printf("bandwidth: %llu (/s)\n", bw);
+                       }
+               }
+       }
+
+       sleep(2);
+       free(buf);
+}
+
+void Send(void *w1, register char *w2, register int size, bool is_lt)
+{
+       register char write_cnt = 0;
+       register char *cptr = (char *)malloc(size);
+
+       sleep(2);
+       for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+               struct timespec clock;
+repeat:
+               if(w2[2] == write_cnt) {
+                       if(write_cnt == 127)
+                               write_cnt = 1;
+                       else
+                               write_cnt++;
+               }
+               else {
+                       goto repeat;
+               }
+
+               memset(cptr, 0, size);
+               if(i >= WARMUP_TRY)
+                       cptr[0] = 'r';
+               else
+                       cptr[0] = 'w';
+               cptr[1] = write_cnt;
+
+               if(is_lt) {
+                       clock_gettime (CLOCK_REALTIME, &clock);
+                       unsigned long long start = (unsigned long long)clock.tv_sec * NS
+                               +(unsigned long long)clock.tv_nsec;
+
+                       memcpy(w1, (void *)&start, sizeof(unsigned long long));
+               }
+               memcpy(w2, cptr, size);
+
+               if(is_lt) {
+                       if(size <= ONE_PAGE_SIZE)
+                               usleep(5000);
+                       else if(size <= 10 * ONE_PAGE_SIZE)
+                               usleep(10000);
+                       else if(size <= 100 * ONE_PAGE_SIZE)
+                               usleep(20000);
+                       else
+                               usleep(40000);
+               }
+       }
+
+       sleep(1);
+       memset(w2, 0, size);
+       free(cptr);
+}
+
+void Measure_bandwidth(void)
+{
+       int ret;
+       char name[25];
+       int returnp[nprocs/2][2];
+       int shm_fd[nprocs/2];
+       void *shm_ptr[nprocs/2];
+       int pids[nprocs];
+       int ready_fd;
+       char *ready_ptr;
+
+       ready_fd = shm_open("isready", O_CREAT | O_TRUNC | O_RDWR, 0666);
+       if(ready_fd == -1)
+       {
+               perror("Open");
+               return;
+       }
+       if(ftruncate(ready_fd, sizeof(char))) {
+               perror("Ftruncate");
+               return;
+       }
+       ready_ptr = mmap(0, sizeof(char), PROT_READ | PROT_WRITE,
+                       MAP_SHARED, ready_fd, 0);
+       if(ready_ptr == MAP_FAILED) {
+               perror("Mmap");
+               return;
+       }
+       close(ready_fd);
+       ready_ptr[0] = "n";
+
+       for(int i = 0; i < nprocs/2; i++) {
+               sprintf(name, "bwsharedmem%d", i);
+               shm_fd[i] = shm_open(name, O_CREAT | O_TRUNC | O_RDWR, 0666);
+               if(shm_fd[i] == -1)
+               {
+                       perror("Open");
+                       return;
+               }
+               if(ftruncate(shm_fd[i], msize)) {
+                       perror("Ftruncate");
+                       return;
+               }
+               shm_ptr[i] = mmap(0, msize, PROT_READ | PROT_WRITE,
+                               MAP_SHARED, shm_fd[i], 0);
+               if(shm_ptr[i] == MAP_FAILED) {
+                       perror("Mmap");
+                       return;
+               }
+       }
+
+       for(int i = 0; i < nprocs/2; i++) {
+               if(pipe(returnp[i]) == -1) {
+                       perror("pipe");
+                       exit(1);
+               }
+       }
+
+       if(!cpu_pin(0, getpid())) {
+               perror("CPU pinning for parent");
+               exit(1);
+       }
+
+       for(int child = 1; child < nprocs; child++) {
+               int pid = fork();
+               switch (pid) {
+                       //child
+                       case 0:
+                               if(!cpu_pin(child, getpid())) {
+                                       perror("CPU pinning for child");
+                                       exit(1);
+                               }
+
+                               // Wait for parent
+                               while(ready_ptr[0] == "n") {
+                               }
+
+                               if(child % 2 == 0) {
+                                       Receive(NULL, shm_ptr[child/2], msize, false);
+
+                                       //send result(bandwidth) to parent
+                                       {
+                                               int wres;
+                                               close(returnp[child/2][0]);
+                                               wres = write(returnp[child/2][1], (void *)&bw, sizeof(unsigned long long));
+                                               if (wres != sizeof(unsigned long long)) {
+                                                       perror("(write return) read/write on pipe sender");
+                                                       exit(1);
+                                               }
+                                               close(returnp[child/2][1]);
+                                       }
+                               }
+                               else {
+                                       Send(NULL, shm_ptr[child/2], msize, false);
+                               }
+                               exit(0);
+                       case -1:
+                               perror("fork");
+                               return;
+                       default:
+                               pids[child] = pid;
+                               break;
+               }
+       }
+
+       sleep(1);
+       ready_ptr[0] = "y";
+
+       Receive(NULL, shm_ptr[0], msize, false);
+       for(int child = 1; child < nprocs; child++) {
+               //receive result(bandwidth) from child(s)
+               if(child % 2 == 0) {
+                       int rres;
+                       unsigned long long child_bw;
+
+                       close(returnp[child/2][1]);
+                       rres = read(returnp[child/2][0], (void *)&child_bw, sizeof(unsigned long long));
+                       if (rres != sizeof(unsigned long long)) {
+                               perror("(read return) read/write on pipe receiver");
+                               exit(1);
+                       }
+                       close(returnp[child/2][0]);
+                       bw += child_bw;
+               }
+
+               waitpid(pids[child], NULL, 0);
+       }
+
+       ret = munmap(ready_ptr, sizeof(bool));
+       if (ret != 0) {
+               perror("munmap");
+               exit(1);
+       }
+
+       ret = shm_unlink("isready");
+       if (ret != 0) {
+               perror("shm unlink");
+               //exit(1);
+       }
+
+       for(int i = 0; i < nprocs/2; i++) {
+               sprintf(name, "bwsharedmem%d", i);
+               ret = munmap(shm_ptr[i], msize);
+               if (ret != 0) {
+                       perror("munmap");
+                       exit(1);
+               }
+
+               ret = shm_unlink(name);
+               if (ret != 0) {
+                       perror("shm unlink");
+                       //exit(1);
+               }
+       }
+
+       printf("Total bandwidth: %llu (/s)\n", bw);
+}
+
+void Measure_latency(void)
+{
+       int ret;
+       int shm_fd[2];
+       void *shm_ptr[2];
+       //      int seals = 0;
+       //      seals | F_SEAL_SHRINK;
+       //      seals | F_SEAL_WRITE;
+       //shm_fd[SHM1] = syscall(SYS_memfd_create, shm_name1, MFD_ALLOW_SEALING);
+       //shm_fd[SHM1] = memfd_create(shm_name1, MFD_ALLOW_SEALING);
+       shm_fd[SHM1] = shm_open(shm_name1, O_CREAT | O_TRUNC | O_RDWR, 0666);
+       if(shm_fd[SHM1] == -1)
+       {
+               perror("Open");
+               return;
+       }
+       if(ftruncate(shm_fd[SHM1], sizeof(unsigned long long))) {
+               perror("Ftruncate");
+               return;
+       }
+       shm_ptr[SHM1] = mmap(0, sizeof(unsigned long long), PROT_READ | PROT_WRITE,
+                       MAP_SHARED, shm_fd[SHM1], 0);
+       if(shm_ptr[SHM1] == MAP_FAILED) {
+               perror("Mmap");
+               return;
+       }
+       /*if(fcntl(shm_fd[SHM1], F_ADD_SEALS, seals) == -1) {
+         perror("Fcntl");
+         return;
+         }*/
+
+       //shm_fd[SHM2] = syscall(SYS_memfd_create, shm_name2, MFD_ALLOW_SEALING);
+       //shm_fd[SHM2] = memfd_create(shm_name2, MFD_ALLOW_SEALING);
+       shm_fd[SHM2] = shm_open(shm_name2, O_CREAT | O_TRUNC | O_RDWR, 0666);
+       if(shm_fd[SHM2] == -1)
+       {
+               perror("Open");
+               return;
+       }
+       if(ftruncate(shm_fd[SHM2], msize)) {
+               perror("Ftruncate");
+               return;
+       }
+       shm_ptr[SHM2] = mmap(0, msize, PROT_READ | PROT_WRITE,
+               MAP_SHARED, shm_fd[SHM2], 0);
+       if(shm_ptr[SHM2] == MAP_FAILED) {
+               perror("Mmap");
+               return;
+       }
+       /*if(fcntl(shm_fd[SHM2], F_ADD_SEALS, seals) == -1) {
+               perror("Fcntl");
+               return;
+       }*/
+
+       if(!cpu_pin(0, getpid())) {
+               perror("CPU pinning for parent");
+               exit(1);
+       }
+
+       int pid = fork();
+       switch (pid) {
+               //child
+               case 0:
+                       if(!cpu_pin(1, getpid())) {
+                               perror("CPU pinning for child");
+                               exit(1);
+                       }
+
+                       Send(shm_ptr[SHM1], shm_ptr[SHM2], msize, true);
+
+                       exit(0);
+               case -1:
+                       perror("fork");
+                       return;
+               default:
+                       Receive(shm_ptr[SHM1], shm_ptr[SHM2], msize, true);
+                       printf("min: %0.4f(us), max: %0.4f(us), avg: %0.4f(us)\n", min, max, total/lt_cnt);
+                       waitpid(pid, NULL, 0);
+                       ret = munmap(shm_ptr[SHM1], sizeof(unsigned long long));
+                       if (ret != 0) {
+                               perror("munmap");
+                               exit(1);
+                       }
+                       ret = shm_unlink(shm_name1);
+                       if (ret != 0) {
+                               perror("munmap");
+                               //exit(1);
+                       }
+
+                       ret = munmap(shm_ptr[SHM2], msize);
+                       if (ret != 0) {
+                               perror("munmap");
+                               exit(1);
+                       }
+
+                       ret = shm_unlink(shm_name2);
+                       if (ret != 0) {
+                               perror("munmap");
+                               //exit(1);
+                       }
+
+                       return;
+       }
+}
+
+       int
+main(int argc, char **argv)
+{
+       int opt;
+       extern char *optarg;
+       extern int optind;
+
+       nprocs = get_nprocs();
+       if(nprocs == 1)
+               nprocs = 2;
+
+       msize = 3;
+       lt_on = bw_on = false;
+       while((opt = getopt(argc, argv, "m:p:blh")) != -1) {
+               switch(opt) {
+               case 'm':
+                       msize = atoi(optarg);
+                       break;
+               case 'p':
+                       nprocs = atoi(optarg);
+                       if(nprocs <= 0) {
+                               printf("The number of process should be larger than 0\n");
+                               exit(0);
+                       }
+                       if(nprocs % 2 != 0) {
+                               printf("The number of process should be even\n");
+                               exit(0);
+                       }
+                       break;
+               case 'b':
+                       bw_on = true;
+                       break;
+               case 'l':
+                       lt_on = true;
+                       break;
+               case 'h':
+                       print_help(argv);
+                       exit(0);
+               }
+       }
+
+       if(!lt_on && !bw_on) {
+               print_help(argv);
+               exit(0);
+       }
+
+       bw = 0;
+       lt_cnt = 0;
+       max = total = 0.0;
+       min = 1000000.0;
+
+       if(lt_on)
+               Measure_latency();
+
+       if(bw_on)
+               Measure_bandwidth();
+}
diff --git a/benchmark/socket.c b/benchmark/socket.c
new file mode 100644 (file)
index 0000000..6945a64
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * lat_socket.c - socket IPC latency
+ *
+ */
+
+#include "common.h"
+
+int nprocs;
+int msize;
+int lt_cnt;
+double min, max, total;
+unsigned long long bw;
+
+bool lt_on, bw_on;
+
+void Receive(int rfd1, int rfd2, register int size, bool is_lt)
+{
+       static int bw_cnt = 0;
+       unsigned long long start;
+       unsigned long long end;
+       register char *buf = (char *)malloc(size);
+
+       for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+               if(is_lt) {
+                       if (read(rfd1, (void *)&start, sizeof(unsigned long long))
+                               != sizeof(unsigned long long)) {
+                               perror("(read 1) read/write on socket parent");
+                               exit(1);
+                       }
+               }
+
+               if (read(rfd2, buf, size) != size) {
+                       perror("(read 2) read/write on socket parent");
+                       exit(1);
+               }
+               else if(buf[0] == 'r'){
+                       struct timespec clock;
+                       if(is_lt) {
+                               clock_gettime (CLOCK_REALTIME, &clock);
+                               end = (unsigned long long)clock.tv_sec * NS
+                                       +(unsigned long long)clock.tv_nsec;
+
+                               double lt = (double)(end - start) / 1000;
+#ifdef DEBUG_ON
+                               printf("latency: %0.4f\n", lt);
+#endif
+
+                               if(lt > 0) {
+                                       lt_cnt++;
+                                       total += lt;
+                                       if(lt > max)
+                                               max = lt;
+
+                                       if(lt < min)
+                                               min = lt;
+                               }
+                       }
+                       else {
+                               bw_cnt++;
+                               if(bw_cnt == 1) {
+                                       clock_gettime (CLOCK_REALTIME, &clock);
+                                       start = (unsigned long long)clock.tv_sec * NS
+                                               + (unsigned long long)clock.tv_nsec;
+                               }
+
+                               if(bw_cnt == REAL_TRY) {
+                                       clock_gettime (CLOCK_REALTIME, &clock);
+                                       end = (unsigned long long)clock.tv_sec * NS
+                                               +(unsigned long long)clock.tv_nsec;
+                                       bw = ((unsigned long long)NS * bw_cnt)/(end - start);
+                                       printf("bandwidth: %llu (/s)\n", bw);
+                               }
+                       }
+               }
+       }
+
+       free(buf);
+}
+
+void Send(int wfd1, int wfd2, register int size, bool is_lt)
+{
+       register char *cptr = (char *)malloc(size);
+
+       sleep(2);
+       for(int i = 0; i < WARMUP_TRY + REAL_TRY; i++) {
+               int wres1, wres2;
+               struct timespec clock;
+
+               memset(cptr, 0, size);
+               if(i >= WARMUP_TRY)
+                       cptr[0] = 'r';
+               else
+                       cptr[0] = 'w';
+
+               if(is_lt) {
+                       clock_gettime (CLOCK_REALTIME, &clock);
+                       unsigned long long start = (unsigned long long)clock.tv_sec * NS
+                               +(unsigned long long)clock.tv_nsec;
+
+                       wres1 = write(wfd1, (void *)&start, sizeof(unsigned long long));
+                       if (wres1 != sizeof(unsigned long long)) {
+                               perror("(write 1) read/write on socket child");
+                               exit(1);
+                       }
+               }
+               wres2 = write(wfd2, cptr, size);
+               if (wres2 != size) {
+                       perror("(write 2) read/write on socket child");
+                       exit(1);
+               }
+
+               if(is_lt) {
+                       if(size <= ONE_PAGE_SIZE)
+                               usleep(5000);
+                       else if(size <= 10 * ONE_PAGE_SIZE)
+                               usleep(10000);
+                       else if(size <= 100 * ONE_PAGE_SIZE)
+                               usleep(20000);
+                       else
+                               usleep(40000);
+               }
+       }
+
+       free(cptr);
+}
+
+void Measure_bandwidth(void)
+{
+       int ret;
+       int returnp[nprocs/2][2];
+       int fd[nprocs/2][2];
+       int pids[nprocs];
+       int ready_fd;
+       char *ready_ptr;
+
+       ready_fd = shm_open("isready", O_CREAT | O_TRUNC | O_RDWR, 0666);
+       if(ready_fd == -1)
+       {
+               perror("Open");
+               return;
+       }
+       if(ftruncate(ready_fd, sizeof(char))) {
+               perror("Ftruncate");
+               return;
+       }
+       ready_ptr = mmap(0, sizeof(char), PROT_READ | PROT_WRITE,
+                       MAP_SHARED, ready_fd, 0);
+       if(ready_ptr == MAP_FAILED) {
+               perror("Mmap");
+               return;
+       }
+       close(ready_fd);
+       ready_ptr[0] = "n";
+
+       for(int i = 0; i < nprocs/2; i++) {
+               if(pipe(returnp[i]) == -1) {
+                       perror("pipe");
+                       exit(1);
+               }
+       }
+
+       for(int i = 0; i < nprocs/2; i++) {
+               if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd[i]) == -1) {
+                       perror("socketpair");
+                       exit(1);
+               }
+       }
+
+       for(int i = 0; i < nprocs/2; i++) {
+               if(pipe(returnp[i]) == -1) {
+                       perror("pipe");
+                       exit(1);
+               }
+       }
+
+       if(!cpu_pin(0, getpid())) {
+               perror("CPU pinning for parent");
+               exit(1);
+       }
+
+       for(int child = 1; child < nprocs; child++) {
+               int pid = fork();
+               switch (pid) {
+                       //child
+                       case 0:
+                               if(!cpu_pin(child, getpid())) {
+                                       perror("CPU pinning for child");
+                                       exit(1);
+                               }
+
+                               // Wait for parent
+                               while(ready_ptr[0] == "n") {
+                               }
+
+                               if(child % 2 == 0) {
+                                       Receive(0, fd[child/2][1], msize, false);
+                                       close(fd[child/2][1]);
+
+                                       //send result(bandwidth) to parent
+                                       {
+                                               int wres;
+                                               close(returnp[child/2][0]);
+                                               wres = write(returnp[child/2][1], (void *)&bw, sizeof(unsigned long long));
+                                               if (wres != sizeof(unsigned long long)) {
+                                                       perror("(write return) read/write on pipe sender");
+                                                       exit(1);
+                                               }
+                                               close(returnp[child/2][1]);
+                                       }
+                               }
+                               else {
+                                       Send(0, fd[child/2][0], msize, false);
+                                       close(fd[child/2][0]);
+                               }
+                               exit(0);
+                       case -1:
+                               perror("fork");
+                               return;
+                       default:
+                               pids[child] = pid;
+                               break;
+               }
+       }
+
+       sleep(1);
+       ready_ptr[0] = "y";
+
+       Receive(0, fd[0][1], msize, false);
+       close(fd[0][1]);
+       for(int child = 1; child < nprocs; child++) {
+               //receive result(bandwidth) from child(s)
+               if(child % 2 == 0) {
+                       int rres;
+                       unsigned long long child_bw;
+
+                       close(returnp[child/2][1]);
+                       rres = read(returnp[child/2][0], (void *)&child_bw, sizeof(unsigned long long));
+                       if (rres != sizeof(unsigned long long)) {
+                               perror("(write return) read/write on pipe receiver");
+                               exit(1);
+                       }
+                       close(returnp[child/2][0]);
+                       bw += child_bw;
+               }
+
+               waitpid(pids[child], NULL, 0);
+       }
+       ret = munmap(ready_ptr, sizeof(bool));
+       if (ret != 0) {
+               perror("munmap");
+               exit(1);
+       }
+
+       ret = shm_unlink("isready");
+       if (ret != 0) {
+               perror("shm unlink");
+               //exit(1);
+       }
+       printf("Total bandwidth: %llu (/s)\n", bw);
+}
+
+void Measure_latency(void)
+{
+       int fd1[2], fd2[2];
+
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd1) == -1) {
+               perror("socketpair");
+               exit(1);
+       }
+
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd2) == -1) {
+               perror("socketpair");
+               exit(1);
+       }
+
+       if(!cpu_pin(0, getpid())) {
+               perror("CPU pinning for parent");
+               exit(1);
+       }
+
+       int pid = fork();
+       switch (pid) {
+               //child
+               case 0:
+                       if(!cpu_pin(1, getpid())) {
+                               perror("CPU pinning for child");
+                               exit(1);
+                       }
+                       Send(fd1[0], fd2[0], msize, true);
+                       close(fd1[0]);
+                       close(fd2[0]);
+                       exit(0);
+               case -1:
+                       perror("fork");
+                       return;
+               default:
+                       Receive(fd1[1], fd2[1], msize, true);
+                       close(fd1[1]);
+                       close(fd2[1]);
+                       printf("min: %0.4f(us), max: %0.4f(us), avg: %0.4f(us)\n", min, max, total/lt_cnt);
+                       waitpid(pid, NULL, 0);
+                       return;
+       }
+}
+
+       int
+main(int argc, char **argv)
+{
+       int opt;
+       extern char *optarg;
+       extern int optind;
+
+       nprocs = get_nprocs();
+       if(nprocs == 1)
+               nprocs = 2;
+
+       msize = 3;
+       lt_on = bw_on = false;
+       while((opt = getopt(argc, argv, "m:p:blh")) != -1) {
+               switch(opt) {
+               case 'm':
+                       msize = atoi(optarg);
+                       break;
+               case 'p':
+                       nprocs = atoi(optarg);
+                       if(nprocs <= 0) {
+                               printf("The number of process should be larger than 0\n");
+                               exit(0);
+                       }
+                       if(nprocs % 2 != 0) {
+                               printf("The number of process should be even\n");
+                               exit(0);
+                       }
+                       break;
+               case 'b':
+                       bw_on = true;
+                       break;
+               case 'l':
+                       lt_on = true;
+                       break;
+               case 'h':
+                       print_help(argv);
+                       exit(0);
+               }
+       }
+
+       if(!lt_on && !bw_on) {
+               print_help(argv);
+               exit(0);
+       }
+
+       bw = 0;
+       lt_cnt = 0;
+       max = total = 0.0;
+       min = 1000000.0;
+
+       if(lt_on)
+               Measure_latency();
+
+       if(bw_on)
+               Measure_bandwidth();
+}
diff --git a/benchmark/test_pc.sh b/benchmark/test_pc.sh
new file mode 100755 (executable)
index 0000000..a388739
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+ARCH="armv7l"
+USER="owner"
+DIR="/home/unsunglee/tizen/output/local/repos/public/$ARCH/RPMS"
+PACKAGE=${PWD##*/}
+TYPE="benchmark"
+VERSION="0.1-1"
+RESULT="/tmp/test_result"
+
+###Build
+gbs build -A $ARCH --include
+
+###Install package
+sdb root on
+sdb push $DIR/$PACKAGE-$TYPE-$VERSION.$ARCH.rpm /tmp
+sdb shell mount -o remount,rw /
+sdb shell rpm -ivh /tmp/$PACKAGE-$TYPE-$VERSION.$ARCH.rpm --nodeps --force
+
+###Running benchmark
+sdb push test_target.sh /home/$USER/test.sh
+#sdb shell chown #USER:users /dev/shm
+echo "##########Running benchmarks"
+echo "##########It takes a little bit of time"
+sdb shell su - $USER /home/$USER/test.sh
+sdb shell rm /home/$USER/test.sh
+sdb pull $RESULT .
+sdb shell rm $RESULT
+
diff --git a/benchmark/test_target.sh b/benchmark/test_target.sh
new file mode 100755 (executable)
index 0000000..46d2f87
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+USER="owner"
+RESULT="/tmp/test_result"
+
+#running benchmark and store results in the file
+echo "##########Pipe##########" >> $RESULT
+pipe -b -l >> $RESULT
+echo "" >> $RESULT
+echo "##########Socket##########" >> $RESULT
+socket -b -l >> $RESULT
+echo "" >> $RESULT
+echo "##########Shared memory##########" >> $RESULT
+sharedmem -b -l >> $RESULT
+echo "" >> $RESULT
+echo "##########Gdbus##########" >> $RESULT
+gdbus -b -l >> $RESULT
+echo "" >> $RESULT
+echo "##########Libdbus##########" >> $RESULT
+libdbus -b -l >> $RESULT
+echo "" >> $RESULT
index 4b4b4516cd308bdb073ef89662a77ae4bc930f88..d8c341216499373aeb068b60718dcfe588764fa4 100644 (file)
@@ -6,24 +6,38 @@ License:   Apache-2.0, MIT
 Requires:  libxslt-tools cynara
 Source:    %{name}-%{version}.tar.gz
 Source101: dbus-tools.manifest
-BuildArch: noarch
+#BuildArch: noarch
 BuildRequires: autoconf
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(dbus-1)
 
 %description
 This package provides a set of tools for working with D-Bus.
 It includes:
 dbuspolicy-checker: a light-weight checker for D-Bus policy files.
 It checks syntax and semantics, looking for common errors.
+benchmark: benchmarks to measure latency and bandwidth of IPC(pipe, shared memory, socket, libdbus, and gdbus).
+
+
+%package benchmark
+Summary:       IPC benchmark
+
+%description benchmark
+This package provides a set of benchmarks to measure latency and bandwidth of IPC
+(pipe, shared memory, socket, libdbus, and gdbus).
 
 %prep
 %setup -q
 cp %{SOURCE101} .
 
 %build
+make
 pushd policychecker
 autoconf
 %configure
 popd
+make
 
 %install
 %make_install
@@ -35,3 +49,10 @@ popd
 %license LICENSE.APACHE2.0 LICENSE.MIT
 %{_bindir}/dbuspolicy-checker
 %{_datadir}/dbus-tools/policychecker/*
+
+%files benchmark
+%{_bindir}/pipe
+%{_bindir}/socket
+%{_bindir}/sharedmem
+%{_bindir}/gdbus
+%{_bindir}/libdbus