Add pipe throughput benchmark
This commit is contained in:
parent
d1731162eb
commit
22edefc349
@ -72,7 +72,7 @@ impl RingBufInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_tail(&self, new_tail: usize) {
|
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 {
|
fn is_closed(&self) -> bool {
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||||
PROJECT_DIR := $(realpath $(CUR_DIR)/../)
|
PROJECT_DIR := $(realpath $(CUR_DIR)/../)
|
||||||
|
|
||||||
# Whether test performance or not?
|
# Dependencies: need to be compiled but not to run by any Makefile target
|
||||||
PERF = yes
|
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)
|
# Top-level Makefile targets
|
||||||
TEST_SUITES := empty argv hello_world malloc file getpid spawn pipe time
|
BUILD_TARGETS := $(TEST_DEPS) $(TESTS) $(BENCHES)
|
||||||
else
|
TEST_TARGETS := $(TESTS:%=test-%)
|
||||||
TEST_SUITES := empty perf_spawn_and_wait4
|
BENCH_TARGETS := $(BENCHES:%=bench-%)
|
||||||
endif
|
CLEAN_TARGETS := $(BUILD_TARGETS:%=clean-%)
|
||||||
BUILD_TEST_SUITES := $(TEST_SUITES:%=%)
|
.PHONY: all build test clean $(BUILD_TARGETS) $(TEST_TARGETS) $(BENCH_TARGETS) $(CLEAN_TARGETS)
|
||||||
RUN_TEST_SUITES := $(TEST_SUITES:%=test-%)
|
|
||||||
CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%)
|
|
||||||
|
|
||||||
# Use echo program instead of built-in echo command in shell. This ensures
|
# Use echo program instead of built-in echo command in shell. This ensures
|
||||||
# that echo can recognize escaped sequences (with -e argument) regardless of
|
# that echo can recognize escaped sequences (with -e argument) regardless of
|
||||||
@ -23,26 +25,24 @@ GREEN := \033[1;32m
|
|||||||
RED := \033[1;31m
|
RED := \033[1;31m
|
||||||
NO_COLOR := \033[0m
|
NO_COLOR := \033[0m
|
||||||
|
|
||||||
.PHONY: all build test clean $(BUILD_TEST_SUITES) $(RUN_TEST_SUITES) $(CLEAN_TEST_SUITES)
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# Build tests
|
# Build targets
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
build: $(BUILD_TEST_SUITES)
|
build: $(BUILD_TARGETS)
|
||||||
|
|
||||||
$(BUILD_TEST_SUITES): %:
|
$(BUILD_TARGETS): %:
|
||||||
@$(ECHO) "$(CYAN)BUILD TEST => $@$(NO_COLOR)"
|
@$(ECHO) "$(CYAN)BUILD TEST => $@$(NO_COLOR)"
|
||||||
@$(MAKE) --no-print-directory -C $@
|
@$(MAKE) --no-print-directory -C $@
|
||||||
@$(ECHO) "$(GREEN)DONE$(NO_COLOR)"
|
@$(ECHO) "$(GREEN)DONE$(NO_COLOR)"
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# Run tests
|
# Test targets
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
test: build $(RUN_TEST_SUITES)
|
test: build $(TEST_TARGETS)
|
||||||
|
|
||||||
pal: $(PROJECT_DIR)/src/pal/pal
|
pal: $(PROJECT_DIR)/src/pal/pal
|
||||||
@cp $< pal
|
@cp $< pal
|
||||||
@ -50,7 +50,7 @@ pal: $(PROJECT_DIR)/src/pal/pal
|
|||||||
libocclum.signed.so: $(PROJECT_DIR)/src/libos/libocclum.signed.so
|
libocclum.signed.so: $(PROJECT_DIR)/src/libos/libocclum.signed.so
|
||||||
@cp $< 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)"
|
@$(ECHO) "$(CYAN)RUN TEST => $<$(NO_COLOR)"
|
||||||
@$(MAKE) --no-print-directory -C $< test ; \
|
@$(MAKE) --no-print-directory -C $< test ; \
|
||||||
if [ $$? -eq 0 ] ; then \
|
if [ $$? -eq 0 ] ; then \
|
||||||
@ -59,12 +59,27 @@ $(RUN_TEST_SUITES): test-%: % pal libocclum.signed.so
|
|||||||
$(ECHO) "$(RED)FAILED$(NO_COLOR)" ; \
|
$(ECHO) "$(RED)FAILED$(NO_COLOR)" ; \
|
||||||
fi ;
|
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
|
# Misc
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
clean: $(CLEAN_TEST_SUITES)
|
clean: $(CLEAN_TARGETS)
|
||||||
@$(RM) -f pal libocclum.signed.so
|
@$(RM) -f pal libocclum.signed.so
|
||||||
|
|
||||||
$(CLEAN_TEST_SUITES): clean-%:
|
$(CLEAN_TARGETS): clean-%:
|
||||||
@$(MAKE) --no-print-directory -C $(patsubst clean-%,%,$@) clean
|
@$(MAKE) --no-print-directory -C $(patsubst clean-%,%,$@) clean
|
||||||
|
33
test/dev_null/main.c
Normal file
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;
|
||||||
|
}
|
5
test/pipe_throughput/Makefile
Normal file
5
test/pipe_throughput/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
include ../test_common.mk
|
||||||
|
|
||||||
|
EXTRA_C_FLAGS := -Wno-incompatible-pointer-types-discards-qualifiers
|
||||||
|
EXTRA_LINK_FLAGS :=
|
||||||
|
BIN_ARGS :=
|
93
test/pipe_throughput/main.c
Normal file
93
test/pipe_throughput/main.c
Normal file
@ -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;
|
||||||
|
}
|
5
test/spawn_and_exit_latency/Makefile
Normal file
5
test/spawn_and_exit_latency/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
include ../test_common.mk
|
||||||
|
|
||||||
|
EXTRA_C_FLAGS :=
|
||||||
|
EXTRA_LINK_FLAGS :=
|
||||||
|
BIN_ARGS :=
|
Loading…
Reference in New Issue
Block a user