Browse Source

Add libreactor (#3237)

* add C/libreactor

* add libreactor to travis configuration

* change platform spec for libreactor
Fredrik Widlund 7 years ago
parent
commit
cfc39fcbbf

+ 1 - 0
.travis.yml

@@ -16,6 +16,7 @@ env:
     - "TESTDIR=C/onion"
     - "TESTDIR=C/h2o"
     - "TESTDIR=C/octane"
+    - "TESTDIR=C/libreactor"
     - "TESTDIR=CSharp/aspnet"
     - "TESTDIR=CSharp/aspnetcore"
     ## - "TESTDIR=CSharp/aspnet-stripped"

+ 11 - 0
frameworks/C/libreactor/Makefile

@@ -0,0 +1,11 @@
+CC     = gcc-6
+PROG   = libreactor
+OBJS   = src/setup.o src/main.o
+CFLAGS = -std=gnu11 -Wall -O3 -march=native -mtune=native -flto -fuse-linker-plugin -Isrc
+LDADD  = -lreactor -ldynamic -lclo
+
+$(PROG): $(OBJS)
+	$(CC) -o $@ $^ $(CFLAGS) $(LDADD)
+
+clean:
+	rm -f $(PROG) $(OBJS)

+ 3 - 0
frameworks/C/libreactor/README.md

@@ -0,0 +1,3 @@
+# libreactor
+
+Benchmarks for the [libreactor](https://github.com/fredrikwidlund/libreactor) library.

+ 27 - 0
frameworks/C/libreactor/benchmark_config.json

@@ -0,0 +1,27 @@
+{
+  "framework": "libreactor",
+  "tests": [
+    {
+      "default": {
+        "setup_file": "setup",
+        "json_url": "/json",
+        "plaintext_url": "/plaintext",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Micro",
+        "database": "None",
+        "framework": "libreactor",
+        "language": "C",
+        "flavor": "None",
+        "orm": "Raw",
+        "platform": "None",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "libreactor",
+        "notes": "",
+        "versus": "None"
+      }
+    }
+  ]
+}

+ 7 - 0
frameworks/C/libreactor/setup.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+fw_depends libreactor
+
+make clean && make
+
+./libreactor &

+ 3 - 0
frameworks/C/libreactor/source_code

@@ -0,0 +1,3 @@
+./src/main.c
+./src/setup.c
+./src/setup.h

+ 140 - 0
frameworks/C/libreactor/src/main.c

@@ -0,0 +1,140 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <sys/resource.h>
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <sys/queue.h>
+#include <linux/sched.h>
+#include <netdb.h>
+#include <err.h>
+
+#include <dynamic.h>
+#include <reactor.h>
+#include <clo.h>
+
+#include "setup.h"
+
+static char date[] = "Thu, 01 Jan 1970 00:00:00 GMT";
+
+static int timer_event(void *state, int type, void *data)
+{
+  (void) state;
+  (void) data;
+  if (type != REACTOR_TIMER_EVENT_CALL)
+    err(1, "timer");
+
+  reactor_http_date(date);
+  return REACTOR_OK;
+}
+
+static int plaintext(reactor_http *http)
+{
+  char content_length[11], *body = "Hello, World!";
+  size_t size;
+
+  size = strlen(body);
+  reactor_util_u32toa(size, content_length);
+  reactor_http_send_response(http, (reactor_http_response[]){{
+        .version = 1,
+	.status = 200,
+	.reason = {"OK", 2},
+	.headers = 4,
+        .header[0] = {{"Server", 6}, {"libreactor", 10}},
+        .header[1] = {{"Date", 4}, {date, strlen(date)}},
+	.header[2] = {{"Content-Type", 12}, {"text/plain", 10}},
+	.header[3] = {{"Content-Length", 14}, {content_length, strlen(content_length)}},
+	.body = {body, size}
+      }});
+  return REACTOR_OK;
+}
+
+static int json(reactor_http *http)
+{
+  char body[4096], content_length[11];
+  size_t size;
+  
+  (void) clo_encode((clo[]) {clo_object({"message", clo_string("Hello, World!")})}, body, sizeof(body));
+  size = strlen(body);
+  reactor_util_u32toa(size, content_length);
+  reactor_http_send_response(http, (reactor_http_response[]){{
+        .version = 1,
+	.status = 200,
+	.reason = {"OK", 2},
+	.headers = 4,
+        .header[0] = {{"Server", 6}, {"libreactor", 10}},
+        .header[1] = {{"Date", 4}, {date, strlen(date)}},
+	.header[2] = {{"Content-Type", 12}, {"application/json", 16}},
+	.header[3] = {{"Content-Length", 14}, {content_length, strlen(content_length)}},
+	.body = {body, size}
+      }});
+  return REACTOR_OK;
+}
+
+int http_event(void *state, int type, void *data)
+{
+  reactor_http *http = state;
+  reactor_http_request *request;
+
+  if (reactor_unlikely(type != REACTOR_HTTP_EVENT_REQUEST))
+    {
+      reactor_http_close(http);
+      free(http);
+      return REACTOR_ABORT;
+    }
+  request = data;
+  
+  if (reactor_http_header_value(&request->path, "/plaintext"))
+    return plaintext(http);
+  else if (reactor_http_header_value(&request->path, "/json"))
+    return json(http);
+  else
+    {
+      reactor_http_send_response(http, (reactor_http_response[]){{
+	    .version = 1,
+	    .status = 404,
+	    .reason = {"Not Found", 9},
+	    .headers = 3,
+            .header[0] = {{"Server", 6}, {"libreactor", 10}},
+            .header[1] = {{"Date", 4}, {date, strlen(date)}},
+	    .header[2] = {{"Content-Length", 14}, {"0", 1}},
+	    .body = {NULL, 0}
+	  }});
+      return REACTOR_OK;
+    }
+}
+
+static int tcp_event(void *state, int type, void *data)
+{
+  reactor_http *http;
+
+  if (type != REACTOR_TCP_EVENT_ACCEPT)
+    err(1, "tcp");
+
+  http = malloc(sizeof *http);
+  if (!http)
+    abort();
+  (void) reactor_http_open(http, http_event, http, *(int *) data, REACTOR_HTTP_FLAG_SERVER);
+  return REACTOR_OK;
+}
+
+int main()
+{
+  reactor_timer timer;
+  reactor_tcp tcp;
+
+  setup(1, 0);  
+  (void) reactor_core_construct();
+  (void) reactor_timer_open(&timer, timer_event, &timer, 1, 1000000000);
+  (void) reactor_tcp_open(&tcp, tcp_event, &tcp, "127.0.0.1", "8080", REACTOR_TCP_FLAG_SERVER);
+  (void) reactor_core_run();
+  reactor_core_destruct();
+}

+ 107 - 0
frameworks/C/libreactor/src/setup.c

@@ -0,0 +1,107 @@
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <err.h>
+
+#include <dynamic.h>
+
+struct cpu
+{
+  int       id;
+  pid_t     pid;
+  cpu_set_t set;
+};
+
+int realtime(void)
+{
+  struct sched_param param;
+  struct rlimit rlim;
+  int e;
+
+  e = sched_getparam(0, &param);
+  if (e == -1)
+    return -1;
+
+  param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+  rlim = (struct rlimit) {.rlim_cur = param.sched_priority, .rlim_max = param.sched_priority};
+  e = prlimit(0, RLIMIT_RTPRIO, &rlim, NULL);
+  if (e == -1)
+    return -1;
+
+  e = sched_setscheduler(0, SCHED_FIFO, &param);
+  if (e == -1)
+    return -1;
+
+  return 0;
+}
+
+static void cpu_list(vector *list, int sib)
+{
+  struct cpu cpu;
+  char path[1024], buf[1024];
+  size_t i, id;
+  ssize_t n;
+  int fd;
+
+  vector_construct(list, sizeof cpu);
+  for (i = 0;; i ++)
+    {
+      snprintf(path, sizeof path, "/sys/devices/system/cpu/cpu%lu/topology/thread_siblings_list", i);
+      fd = open(path, O_RDONLY);
+      if (fd == -1)
+        break;
+      n = read(fd, buf, sizeof buf - 1);
+      if (n == -1)
+        err(1, "read");
+      buf[n] = 0;
+      close(fd);
+
+      id = strtoul(buf, NULL, 0);
+      if (!sib && id != i)
+        continue;
+
+      cpu = (struct cpu) {0};
+      cpu.id = id;
+      CPU_ZERO(&cpu.set);
+      CPU_SET(id, &cpu.set);
+      vector_push_back(list, &cpu);
+    }
+}
+
+void setup(size_t skip, int sib)
+{
+  vector list;
+  struct cpu *cpu;
+  size_t i;
+  int e;
+  pid_t cpid;
+
+  signal(SIGPIPE, SIG_IGN);
+  cpu_list(&list, sib);
+  for (i = 0; i < vector_size(&list); i ++)
+    {
+      if (i % skip != 0)
+        continue;
+      cpu = vector_at(&list, i);
+      cpid = fork();
+      if (cpid == -1)
+        err(1, "fork");
+      if (cpid == 0)
+        {
+          e = sched_setaffinity(0, sizeof cpu->set, &cpu->set);
+          if (e == -1)
+            err(1, "sched_setaffinity");
+          return;
+        }
+      cpu->pid = cpid;
+    }
+  wait(NULL);
+  vector_destruct(&list, NULL);
+}

+ 6 - 0
frameworks/C/libreactor/src/setup.h

@@ -0,0 +1,6 @@
+#ifndef SETUP_H_INCLUDED
+#define SETUP_H_INCLUDED
+
+void setup(size_t, int);
+
+#endif /* SETUP_H_INCLUDED */

+ 37 - 0
toolset/setup/linux/frameworks/libreactor.sh

@@ -0,0 +1,37 @@
+#!/bin/bash
+
+fw_depends gcc-6
+
+fw_installed libreactor && return 0
+
+mkdir -p ${CROOT} || true
+cd ${CROOT}
+
+LIBREACTOR_HOME=$IROOT/libreactor
+mkdir -p $LIBREACTOR_HOME
+
+cd $LIBREACTOR_HOME
+wget https://github.com/fredrikwidlund/libdynamic/releases/download/v1.1.0/libdynamic-1.1.0.tar.gz
+tar xfz libdynamic-1.1.0.tar.gz
+cd libdynamic-1.1.0
+./configure CC=gcc-6 AR=gcc-ar-6 NM=gcc-nm-6 RANLIB=gcc-ranlib-6
+make && sudo make install
+
+cd $LIBREACTOR_HOME
+wget https://github.com/fredrikwidlund/libreactor/releases/download/v1.0.0/libreactor-1.0.0.tar.gz
+tar xfz libreactor-1.0.0.tar.gz
+cd libreactor-1.0.0
+./configure CC=gcc-6 AR=gcc-ar-6 NM=gcc-nm-6 RANLIB=gcc-ranlib-6
+make && sudo make install
+
+cd $LIBREACTOR_HOME
+wget https://github.com/fredrikwidlund/libclo/releases/download/v0.1.0/libclo-0.1.0.tar.gz
+tar xfz libclo-0.1.0.tar.gz
+cd libclo-0.1.0
+./configure CC=gcc-6 AR=gcc-ar-6 NM=gcc-nm-6 RANLIB=gcc-ranlib-6
+make && sudo make install
+
+cd $LIBREACTOR_HOME
+echo "export LIBREACTOR_HOME=${LIBREACTOR_HOME}" >> $IROOT/libreactor.installed
+
+source $IROOT/libreactor.installed