Skip to content

Commit

Permalink
add benchmark source code and documents
Browse files Browse the repository at this point in the history
  • Loading branch information
sonullx committed Sep 4, 2020
1 parent 9c7d164 commit eb922b9
Show file tree
Hide file tree
Showing 13 changed files with 543 additions and 0 deletions.
41 changes: 41 additions & 0 deletions benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
cmake_minimum_required(VERSION 3.6)

set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "build type")

project(benchmark
LANGUAGES C CXX
)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR})

find_library(LIBRT rt)
find_package(OpenSSL REQUIRED)
find_package(workflow REQUIRED CONFIG HINTS ..)
include_directories(${OPENSSL_INCLUDE_DIR} ${WORKFLOW_INCLUDE_DIR})
link_directories(${WORKFLOW_LIB_DIR})

if (WIN32)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP /wd4200")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /wd4200 /std:c++14")
else ()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fPIC -pipe -std=gnu90")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fPIC -pipe -std=c++11 -fno-exceptions")
endif ()

set(BENCHMARK_LIST
benchmark-01-http_server
benchmark-02-http_server_slow
)

if (APPLE)
set(WORKFLOW_LIB workflow pthread z OpenSSL::SSL OpenSSL::Crypto)
else ()
set(WORKFLOW_LIB workflow ${LIBRT})
endif ()

foreach(src ${BENCHMARK_LIST})
string(REPLACE "-" ";" arr ${src})
list(GET arr -1 bin_name)
add_executable(${bin_name} ${src}.cc)
target_link_libraries(${bin_name} ${WORKFLOW_LIB})
endforeach()
27 changes: 27 additions & 0 deletions benchmark/GNUmakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
ALL_TARGETS := all clean
MAKE_FILE := Makefile

DEFAULT_BUILD_DIR := build
BUILD_DIR := $(shell if [ -f $(MAKE_FILE) ]; then echo "."; else echo $(DEFAULT_BUILD_DIR); fi)
CMAKE3 := $(shell if which cmake3>/dev/null ; then echo cmake3; else echo cmake; fi;)

.PHONY: $(ALL_TARGETS)

all:
mkdir -p $(BUILD_DIR)
ifeq ($(DEBUG),y)
cd $(BUILD_DIR) && $(CMAKE3) -D CMAKE_BUILD_TYPE=Debug $(ROOT_DIR)
else
cd $(BUILD_DIR) && $(CMAKE3) $(ROOT_DIR)
endif
make -C $(BUILD_DIR) -f Makefile

clean:
ifeq ($(MAKE_FILE), $(wildcard $(MAKE_FILE)))
-make -f Makefile clean
else ifeq (build, $(wildcard build))
-make -C build clean
endif
rm -rf build

58 changes: 58 additions & 0 deletions benchmark/benchmark-01-http_server.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <csignal>

#include <workflow/WFHttpServer.h>
#include <workflow/WFGlobal.h>
#include <workflow/WFFacilities.h>

#include "util/args.h"
#include "util/content.h"
#include "util/date.h"

static WFFacilities::WaitGroup wait_group{1};

void signal_handler(int)
{
wait_group.done();
}

int main(int argc, char ** argv)
{
size_t pollers;
unsigned short port;
size_t length;

if (parse_args(argc, argv, pollers, port, length) != 3)
{
return -1;
}

std::signal(SIGINT, signal_handler);
std::signal(SIGTERM, signal_handler);

WFGlobalSettings settings = GLOBAL_SETTINGS_DEFAULT;
settings.poller_threads = pollers;
WORKFLOW_library_init(&settings);

const std::string content = make_content(length);
WFHttpServer server([&content](WFHttpTask * task)
{
auto * resp = task->get_resp();

char timestamp[32];
date(timestamp, sizeof(timestamp));
resp->add_header_pair("Date", timestamp);

resp->add_header_pair("Content-Type", "text/plain; charset=UTF-8");

resp->append_output_body_nocopy(content.data(), content.size());
});

if (server.start(port) == 0)
{
wait_group.wait();
server.stop();
}

return 0;
}

68 changes: 68 additions & 0 deletions benchmark/benchmark-02-http_server_long_req.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include <csignal>
#include <cstring>

#include <workflow/WFHttpServer.h>
#include <workflow/WFGlobal.h>
#include <workflow/WFFacilities.h>

#include "util/args.h"
#include "util/content.h"
#include "util/date.h"

static WFFacilities::WaitGroup wait_group{1};

void signal_handler(int)
{
wait_group.done();
}

int main(int argc, char ** argv)
{
size_t pollers;
unsigned short port;
size_t length;
size_t microseconds;

if (parse_args(argc, argv, pollers, port, length, microseconds) != 4)
{
return -1;
}

std::signal(SIGINT, signal_handler);
std::signal(SIGTERM, signal_handler);

WFGlobalSettings settings = GLOBAL_SETTINGS_DEFAULT;
settings.poller_threads = pollers;
WORKFLOW_library_init(&settings);

const std::string content = make_content(length);
WFHttpServer server([&content, &microseconds](WFHttpTask * task)
{
auto resp = task->get_resp();

char timestamp[32];
date(timestamp, sizeof(timestamp));
resp->add_header_pair("Date", timestamp);

resp->add_header_pair("Content-Type", "text/plain; charset=UTF-8");

resp->append_output_body_nocopy(content.data(), content.size());

auto req = task->get_req();
auto uri = req->get_request_uri();
if (std::strcmp(uri, "/long_req/") == 0)
{
auto timer_task = WFTaskFactory::create_timer_task(microseconds, nullptr);
series_of(task)->push_back(timer_task);
}
});

if (server.start(port) == 0)
{
wait_group.wait();
server.stop();
}

return 0;
}

102 changes: 102 additions & 0 deletions benchmark/util/args.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#ifndef _BENCHMARK_ARGS_H_
#define _BENCHMARK_ARGS_H_

#include <algorithm>
#include <numeric>
#include <string>

namespace details
{
template <typename T>
bool extract(const char *, T &);

template <typename ... ARGS>
int parse(int todo, char ** p, ARGS & ... args);

template <>
int parse(int todo, char ** p)
{
return 0;
}

template <typename T, typename ... ARGS>
int parse(int todo, char ** p, T & t, ARGS & ... args)
{
if (todo != 0 && extract(*p, t))
{
return parse(todo - 1, p + 1, args ...) + 1;
}
return 0;
}

template <typename ... ARGS>
int parse_args(int & argc, char ** argv, ARGS & ... args)
{
if (argc <= 1)
{
return 0;
}

int length = argc - 1;
char ** begin = argv + 1;
char ** end = begin + length;

int done = parse(length, begin, args ...);
std::rotate(begin, begin + done, end);
std::reverse(end - done, end);

argc -= done;
return done;
}

template <>
bool extract<size_t>(const char * p, size_t & t)
{
char * e;
long long ll = std::strtoll(p, &e, 0);
if (*e || ll < 0)
{
return false;
}
t = static_cast<size_t>(ll);
return true;
}

template <>
bool extract<unsigned short>(const char * p, unsigned short & t)
{
char * e;
long long ll = std::strtoll(p, &e, 0);
if (*e
|| ll < static_cast<long long>(std::numeric_limits<unsigned short>::min())
|| ll > static_cast<long long>(std::numeric_limits<unsigned short>::max())
)
{
return false;
}
t = static_cast<unsigned short>(ll);
return true;
}

template <>
bool extract<std::string>(const char * p, std::string & t)
{
t = p;
return true;
}

template <>
bool extract<const char *>(const char * p, const char *& t)
{
t = p;
return true;
}
}

template <typename ... ARGS>
static int parse_args(int & argc, char ** argv, ARGS & ... args)
{
return details::parse_args(argc, argv, args ...);
}

#endif //_BENCHMARK_ARGS_H_
21 changes: 21 additions & 0 deletions benchmark/util/content.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef _BENCHMARK_CONTENT_H_
#define _BENCHMARK_CONTENT_H_

#include <random>
#include <string>

static inline std::string make_content(size_t length)
{
std::mt19937_64 gen{42};
std::uniform_int_distribution<int> dis{32, 126};

std::string s;
s.reserve(length);
for (size_t i = 0; i < length; i++)
{
s.push_back(static_cast<char>(dis(gen)));
}
return s;
}

#endif //_BENCHMARK_CONTENT_H_
15 changes: 15 additions & 0 deletions benchmark/util/date.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef _BENCHMARK_DATE_H_
#define _BENCHMARK_DATE_H_

#include <ctime>

static inline void date(char * buf, size_t n)
{
auto tt = std::time(nullptr);
std::tm cur{};
// gmtime_r(&tt, &cur);
localtime_r(&tt, &cur);
strftime(buf, n, "%a, %d %b %Y %H:%M:%S %Z", &cur);
}

#endif //_BENCHMARK_DATE_H_
Loading

0 comments on commit eb922b9

Please sign in to comment.