From aa052d9c79739bff661652519f45841deda36618 Mon Sep 17 00:00:00 2001 From: Wojtek Porczyk Date: Thu, 8 Oct 2020 16:57:15 +0200 Subject: [PATCH] [ci] Add benchmarks Add benchmark framework and some example benchmarks. More will come later. There is no integration into CI yet. --- .gitignore | 2 + asv.conf.json | 112 +++++++++++++++++++++++++++++++++++++++ benchmarks/.gitignore | 7 +++ benchmarks/Makefile | 46 ++++++++++++++++ benchmarks/__init__.py | 0 benchmarks/benchmarks.py | 24 +++++++++ benchmarks/helloworld.c | 4 ++ benchmarks/manifest.in | 25 +++++++++ benchmarks/write_pages.c | 54 +++++++++++++++++++ 9 files changed, 274 insertions(+) create mode 100644 asv.conf.json create mode 100644 benchmarks/.gitignore create mode 100644 benchmarks/Makefile create mode 100644 benchmarks/__init__.py create mode 100644 benchmarks/benchmarks.py create mode 100644 benchmarks/helloworld.c create mode 100644 benchmarks/manifest.in create mode 100644 benchmarks/write_pages.c diff --git a/.gitignore b/.gitignore index 5130c9f4..5e8a12b3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.asv/ + # No editor backup files. *.sw* *.backup diff --git a/asv.conf.json b/asv.conf.json new file mode 100644 index 00000000..e7439004 --- /dev/null +++ b/asv.conf.json @@ -0,0 +1,112 @@ +{ + // The version of the config file format. Do not change, unless + // you know what you are doing. + "version": 1, + + // The name of the project being benchmarked + "project": "project", + + // The project's homepage + "project_url": "https://graphene.readthedocs.io/", + + // The URL or local path of the source code repository for the + // project being benchmarked + "repo": ".", + + "plugins": [ +// ".benchmarks.yoloenv" + ], + + // The Python project's subdirectory in your repo. If missing or + // the empty string, the project is assumed to be located at the root + // of the repository. + // "repo_subdir": "", + + // Customizable commands for building, installing, and + // uninstalling the project. See asv.conf.json documentation. + // + // "install_command": ["in-dir={env_dir} python -mpip install {wheel_file}"], + // "uninstall_command": ["return-code=any python -mpip uninstall -y {project}"], + "build_command": [ + "python3 -m pip install protobuf", + "openssl genrsa -3 -out Pal/src/host/Linux-SGX/signer/enclave-key.pem 3072", + "make -j8 SGX=1 WERROR=1 ISGX_DRIVER_PATH=/opt/intel/linux-sgx-driver", + "make -j8 SGX=1 WERROR=1 ISGX_DRIVER_PATH=/opt/intel/linux-sgx-driver sgx-tokens", + "make -j8 -C benchmarks" + ], + + // List of branches to benchmark. If not provided, defaults to "master" + // (for git) or "default" (for mercurial). + // "branches": ["master"], // for git + // "branches": ["default"], // for mercurial + + // The tool to use to create environments. May be "conda", + // "virtualenv" or other value depending on the plugins in use. + // If missing or the empty string, the tool will be automatically + // determined by looking for tools on the PATH environment + // variable. + "environment_type": "existing", + + // timeout in seconds for installing any dependencies in environment + // defaults to 10 min + //"install_timeout": 600, + + // the base URL to show a commit for the project. + "show_commit_url": "http://github.com/oscarlab/graphene/commit/", + + // The Pythons you'd like to test against. If not provided, defaults + // to the current version of Python used to run `asv`. + "pythons": ["same"], + + // The list of conda channel names to be searched for benchmark + // dependency packages in the specified order + // "conda_channels": ["conda-forge", "defaults"], + + // The directory (relative to the current directory) that benchmarks are + // stored in. If not provided, defaults to "benchmarks" + // "benchmark_dir": "benchmarks", + + // The directory (relative to the current directory) to cache the Python + // environments in. If not provided, defaults to "env" + "env_dir": ".asv/env", + + // The directory (relative to the current directory) that raw benchmark + // results are stored in. If not provided, defaults to "results". + "results_dir": ".asv/results", + + // The directory (relative to the current directory) that the html tree + // should be written to. If not provided, defaults to "html". + "html_dir": ".asv/html", + + // The number of characters to retain in the commit hashes. + // "hash_length": 8, + + // `asv` will cache results of the recent builds in each + // environment, making them faster to install next time. This is + // the number of builds to keep, per environment. + // "build_cache_size": 2, + + // The commits after which the regression search in `asv publish` + // should start looking for regressions. Dictionary whose keys are + // regexps matching to benchmark names, and values corresponding to + // the commit (exclusive) after which to start looking for + // regressions. The default is to start from the first commit + // with results. If the commit is `null`, regression detection is + // skipped for the matching benchmark. + // + // "regressions_first_commits": { + // "some_benchmark": "352cdf", // Consider regressions only after this commit + // "another_benchmark": null, // Skip regression detection altogether + // }, + + // The thresholds for relative change in results, after which `asv + // publish` starts reporting regressions. Dictionary of the same + // form as in ``regressions_first_commits``, with values + // indicating the thresholds. If multiple entries match, the + // maximum is taken. If no entry matches, the default is 5%. + // + // "regressions_thresholds": { + // "some_benchmark": 0.01, // Threshold of 1% + // "another_benchmark": 0.5, // Threshold of 50% + // }, +} diff --git a/benchmarks/.gitignore b/benchmarks/.gitignore new file mode 100644 index 00000000..4335c205 --- /dev/null +++ b/benchmarks/.gitignore @@ -0,0 +1,7 @@ +__pycache__/ +*.manifest +*.manifest.sgx +*.sig +*.token +helloworld +write_1e[4567] diff --git a/benchmarks/Makefile b/benchmarks/Makefile new file mode 100644 index 00000000..2c08a2e2 --- /dev/null +++ b/benchmarks/Makefile @@ -0,0 +1,46 @@ +BENCHMARKS = \ + helloworld \ + write_1e4 \ + write_1e5 \ + write_1e6 \ + write_1e7 +GRAPHENEDIR = $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/.. ) +signer = ../Pal/src/host/Linux-SGX/signer + + +all: $(BENCHMARKS) $(patsubst %,%.token,$(BENCHMARKS)) + +$(filter write_%,$(BENCHMARKS)): %: write_pages.c + $(CC) $(CFLAGS) $< -o $@ +write_1e4 : CFLAGS += -DPAGECOUNT=10000 +write_1e5 : CFLAGS += -DPAGECOUNT=100000 +write_1e6 : CFLAGS += -DPAGECOUNT=1000000 +write_1e7 : CFLAGS += -DPAGECOUNT=10000000 + +%.manifest: manifest.in + sed \ + -e 's:@GRAPHENEDIR@:$(GRAPHENEDIR):g' $< \ + > $@ + +.PRECIOUS: %.manifest.sgx +%.manifest.sgx: % %.manifest + $(signer)/pal-sgx-sign \ + --exec $< \ + --manifest $<.manifest \ + --output $@ \ + --key $(signer)/enclave-key.pem \ + --libpal ../Runtime/libpal-Linux-SGX.so + +%.token: %.manifest.sgx + $(signer)/pal-sgx-get-token \ + --sig $*.sig \ + --output $@ + +.PHONY: clean +clean: + $(RM) \ + $(BENCHMARKS) \ + $(patsubst %,%.manifest,$(BENCHMARKS)) \ + $(patsubst %,%.manifest.sgx,$(BENCHMARKS)) \ + $(patsubst %,%.sig,$(BENCHMARKS)) \ + $(patsubst %,%.token,$(BENCHMARKS)) diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/benchmarks/benchmarks.py b/benchmarks/benchmarks.py new file mode 100644 index 00000000..d938885d --- /dev/null +++ b/benchmarks/benchmarks.py @@ -0,0 +1,24 @@ +import os +import pathlib +import subprocess + + +def setup(): + os.environ['SGX'] = '1' + +_cwd = pathlib.Path(__file__).parent.absolute() +def _run(stem): + subprocess.run([os.fspath('../Runtime/pal_loader'), stem + '.manifest.sgx'], + check=True, cwd=os.fspath(_cwd)) + +def time_000_helloworld(): + _run('helloworld') + +def time_014_write_1e4(): + _run('write_1e4') +def time_015_write_1e5(): + _run('write_1e5') +def time_016_write_1e6(): + _run('write_1e6') +def time_017_write_1e7(): + _run('write_1e7') diff --git a/benchmarks/helloworld.c b/benchmarks/helloworld.c new file mode 100644 index 00000000..a46866d9 --- /dev/null +++ b/benchmarks/helloworld.c @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/benchmarks/manifest.in b/benchmarks/manifest.in new file mode 100644 index 00000000..406fe4ae --- /dev/null +++ b/benchmarks/manifest.in @@ -0,0 +1,25 @@ +#sgx.enable_stats = 1 + +loader.preload = file:@GRAPHENEDIR@/Runtime/libsysdb.so +loader.env.LD_LIBRARY_PATH = /lib +loader.debug_type = none +loader.syscall_symbol = syscalldb +loader.insecure__use_cmdline_argv = 1 + +fs.mount.graphene_lib.type = chroot +fs.mount.graphene_lib.path = /lib +fs.mount.graphene_lib.uri = file:@GRAPHENEDIR@/Runtime + +sgx.trusted_files.ld = file:@GRAPHENEDIR@/Runtime/ld-linux-x86-64.so.2 +sgx.trusted_files.libc = file:@GRAPHENEDIR@/Runtime/libc.so.6 +sgx.trusted_files.libdl = file:@GRAPHENEDIR@/Runtime/libdl.so.2 +sgx.trusted_files.libm = file:@GRAPHENEDIR@/Runtime/libm.so.6 +sgx.trusted_files.libpthread = file:@GRAPHENEDIR@/Runtime/libpthread.so.0 +#sgx.trusted_files.libgcc_s = file:$(ARCH_LIBDIR)/libgcc_s.so.1 +#sgx.trusted_files.libstdcxx = file:/usr$(ARCH_LIBDIR)/libstdc++.so.6 + +#sgx.allow_file_creation = 1 + +sgx.thread_num = 3 + +#sgx.static_address = 1 diff --git a/benchmarks/write_pages.c b/benchmarks/write_pages.c new file mode 100644 index 00000000..33ee29fc --- /dev/null +++ b/benchmarks/write_pages.c @@ -0,0 +1,54 @@ +/* + * write a number of pages to /dev/null + */ + +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + void *buf; + size_t pagesize; + ssize_t r; + int fd, i, ret; + + ret = -1; + + pagesize = sysconf(_SC_PAGESIZE); + + buf = mmap(NULL, pagesize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if (buf == MAP_FAILED) { + perror("mmap"); + goto err_return; + } + + memset(buf, 0xa5, pagesize); + + fd = open("/dev/null", O_WRONLY); + if (fd < 0) { + perror("open"); + goto err_unmap; + } + + for (i = 0; i < PAGECOUNT; i++) { + r = write(fd, buf, pagesize); + if (r < 0) { + perror("write"); + goto err_close; + } + } + + ret = 0; + +err_close: + close(fd); +err_unmap: + munmap(buf, pagesize); +err_return: + return ret; +}