Add pipe throughput benchmark

This commit is contained in:
Tate, Hongliang Tian 2019-01-08 23:25:59 +08:00
parent d1731162eb
commit 22edefc349
8 changed files with 172 additions and 21 deletions

@ -72,7 +72,7 @@ impl RingBufInner {
}
fn set_tail(&self, new_tail: usize) {
self.head.store(new_tail, Ordering::SeqCst)
self.tail.store(new_tail, Ordering::SeqCst)
}
fn is_closed(&self) -> bool {

@ -1,17 +1,19 @@
CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
PROJECT_DIR := $(realpath $(CUR_DIR)/../)
# Whether test performance or not?
PERF = yes
# Dependencies: need to be compiled but not to run by any Makefile target
TEST_DEPS := dev_null
# Tests: need to be compiled and run by test-% target
TESTS := empty argv hello_world malloc file getpid spawn pipe time
# Benchmarks: need to be compiled and run by bench-% target
BENCHES := spawn_and_exit_latency pipe_throughput
ifeq ($(PERF),no)
TEST_SUITES := empty argv hello_world malloc file getpid spawn pipe time
else
TEST_SUITES := empty perf_spawn_and_wait4
endif
BUILD_TEST_SUITES := $(TEST_SUITES:%=%)
RUN_TEST_SUITES := $(TEST_SUITES:%=test-%)
CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%)
# Top-level Makefile targets
BUILD_TARGETS := $(TEST_DEPS) $(TESTS) $(BENCHES)
TEST_TARGETS := $(TESTS:%=test-%)
BENCH_TARGETS := $(BENCHES:%=bench-%)
CLEAN_TARGETS := $(BUILD_TARGETS:%=clean-%)
.PHONY: all build test clean $(BUILD_TARGETS) $(TEST_TARGETS) $(BENCH_TARGETS) $(CLEAN_TARGETS)
# Use echo program instead of built-in echo command in shell. This ensures
# that echo can recognize escaped sequences (with -e argument) regardless of
@ -23,26 +25,24 @@ GREEN := \033[1;32m
RED := \033[1;31m
NO_COLOR := \033[0m
.PHONY: all build test clean $(BUILD_TEST_SUITES) $(RUN_TEST_SUITES) $(CLEAN_TEST_SUITES)
#############################################################################
# Build tests
# Build targets
#############################################################################
all: build
build: $(BUILD_TEST_SUITES)
build: $(BUILD_TARGETS)
$(BUILD_TEST_SUITES): %:
$(BUILD_TARGETS): %:
@$(ECHO) "$(CYAN)BUILD TEST => $@$(NO_COLOR)"
@$(MAKE) --no-print-directory -C $@
@$(ECHO) "$(GREEN)DONE$(NO_COLOR)"
#############################################################################
# Run tests
# Test targets
#############################################################################
test: build $(RUN_TEST_SUITES)
test: build $(TEST_TARGETS)
pal: $(PROJECT_DIR)/src/pal/pal
@cp $< pal
@ -50,7 +50,7 @@ pal: $(PROJECT_DIR)/src/pal/pal
libocclum.signed.so: $(PROJECT_DIR)/src/libos/libocclum.signed.so
@cp $< libocclum.signed.so
$(RUN_TEST_SUITES): test-%: % pal libocclum.signed.so
$(TEST_TARGETS): test-%: % pal libocclum.signed.so
@$(ECHO) "$(CYAN)RUN TEST => $<$(NO_COLOR)"
@$(MAKE) --no-print-directory -C $< test ; \
if [ $$? -eq 0 ] ; then \
@ -59,12 +59,27 @@ $(RUN_TEST_SUITES): test-%: % pal libocclum.signed.so
$(ECHO) "$(RED)FAILED$(NO_COLOR)" ; \
fi ;
#############################################################################
# Benchmark targets
#############################################################################
bench: build $(BENCH_TARGETS)
$(BENCH_TARGETS): bench-%: % pal libocclum.signed.so
@$(ECHO) "$(CYAN)RUN BENCH => $<$(NO_COLOR)"
@$(MAKE) --no-print-directory -C $< test ; \
if [ $$? -eq 0 ] ; then \
$(ECHO) "$(GREEN)DONE$(NO_COLOR)" ; \
else \
$(ECHO) "$(RED)FAILED$(NO_COLOR)" ; \
fi ;
#############################################################################
# Misc
#############################################################################
clean: $(CLEAN_TEST_SUITES)
clean: $(CLEAN_TARGETS)
@$(RM) -f pal libocclum.signed.so
$(CLEAN_TEST_SUITES): clean-%:
$(CLEAN_TARGETS): clean-%:
@$(MAKE) --no-print-directory -C $(patsubst clean-%,%,$@) clean

33
test/dev_null/main.c Normal file

@ -0,0 +1,33 @@
#include <unistd.h>
#include <stdio.h>
#define MAX_BUF_SIZE (1 * 1024 * 1024)
#define MIN(x, y) ((x) <= (y) ? (x) : (y))
int main(int argc, const char* argv[]) {
// Get the total number of bytes to read
size_t remain_bytes = 0;
while (read(0, &remain_bytes, sizeof(remain_bytes)) != sizeof(remain_bytes));
// Get the size of buffer to use
size_t buf_size = 0;
while (read(0, &buf_size, sizeof(buf_size)) != sizeof(buf_size));
if (buf_size > MAX_BUF_SIZE) {
printf("ERROR: the required buffer size (%lu) is tool large\n", buf_size);
return -1;
}
// Read a specified amount of data in a buffer of specified size
char buf[MAX_BUF_SIZE];
while (remain_bytes > 0) {
size_t len = MIN(buf_size, remain_bytes);
if ((len = read(0, &buf, len)) < 0) {
printf("ERROR: failed to write to pipe\n");
return -1;
}
remain_bytes -= len;
}
return 0;
}

@ -0,0 +1,5 @@
include ../test_common.mk
EXTRA_C_FLAGS := -Wno-incompatible-pointer-types-discards-qualifiers
EXTRA_LINK_FLAGS :=
BIN_ARGS :=

@ -0,0 +1,93 @@
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <spawn.h>
#include <string.h>
#define KB (1024UL)
#define MB (1024UL * 1024UL)
#define GB (1024UL * 1024UL * 1024UL)
#define TOTAL_BYTES (2 * GB)
#define BUF_SIZE (128 * KB)
#define MIN(x, y) ((x) <= (y) ? (x) : (y))
int main(int argc, const char* argv[]) {
// Create pipe
int pipe_fds[2];
if (pipe(pipe_fds) < 0) {
printf("ERROR: failed to create a pipe\n");
return -1;
}
int pipe_rd_fd = pipe_fds[0];
int pipe_wr_fd = pipe_fds[1];
// Spawn a child process that reads from the pipe
posix_spawn_file_actions_t file_actions;
posix_spawn_file_actions_init(&file_actions);
posix_spawn_file_actions_adddup2(&file_actions, pipe_rd_fd, STDIN_FILENO);
posix_spawn_file_actions_addclose(&file_actions, pipe_wr_fd);
int child_pid;
if (posix_spawn(&child_pid, "dev_null/bin.encrypted", &file_actions,
NULL, NULL, NULL) < 0) {
printf("ERROR: failed to spawn a child process\n");
return -1;
}
close(pipe_rd_fd);
// Start the timer
struct timeval tv_start, tv_end;
gettimeofday(&tv_start, NULL);
// Tell the reader how many data are to be transfered
size_t remain_bytes = TOTAL_BYTES;
if (write(pipe_wr_fd, &remain_bytes, sizeof(remain_bytes)) != sizeof(remain_bytes)) {
printf("ERROR: failed to write to pipe\n");
return -1;
}
// Tell the reader the buffer size that it should use
size_t buf_size = BUF_SIZE;
if (write(pipe_wr_fd, &buf_size, sizeof(buf_size)) != sizeof(buf_size)) {
printf("ERROR: failed to write to pipe\n");
return -1;
}
// Write a specified amount of data in a buffer of specified size
char buf[BUF_SIZE] = {0};
while (remain_bytes > 0) {
size_t len = MIN(buf_size, remain_bytes);
if ((len = write(pipe_wr_fd, &buf, len)) < 0) {
printf("ERROR: failed to write to pipe\n");
return -1;
}
remain_bytes -= len;
}
// Wait for the child process to read all data and exit
int status = 0;
if (wait4(child_pid, &status, 0, NULL) < 0) {
printf("ERROR: failed to wait4 the child process\n");
return -1;
}
// Stop the timer
gettimeofday(&tv_end, NULL);
// Calculate the throughput
double total_s = (tv_end.tv_sec - tv_start.tv_sec)
+ (double)(tv_end.tv_usec - tv_start.tv_usec) / 1000000;
if (total_s < 1.0) {
printf("WARNING: run long enough to get meaningful results\n");
if (total_s == 0) { return 0; }
}
double total_mb = (double)TOTAL_BYTES / MB;
double throughput = total_mb / total_s;
printf("Throughput of pipe is %.2f MB/s\n", throughput);
return 0;
}

@ -0,0 +1,5 @@
include ../test_common.mk
EXTRA_C_FLAGS :=
EXTRA_LINK_FLAGS :=
BIN_ARGS :=