├── .gitattributes
├── .gitignore
├── .vscode
├── launch.json
├── settings.json
└── tasks.json
├── Makefile
├── Makefile_DPDK
├── Makefile_PCAP
├── Makefile_deprecated
├── README.md
├── doc
├── 00-a-tour-of-rubik.markdown
├── 01-layout-and-header-stage.markdown
├── 02-expression-and-variable.markdown
├── 03-semantic-completeness.markdown
├── 04-peephole-optimizations.markdown
└── 04-peephole-optimizations.png
├── native
├── drivers
│ ├── dpdk.c
│ ├── dpdk_deprecated.c
│ └── pcap.c
├── runtime
│ ├── Makefile
│ ├── malloc.h
│ ├── profile.c
│ ├── profile.h
│ ├── seq.h
│ ├── seq_next.h
│ ├── seq_test.c
│ ├── timer.h
│ ├── tommyds
│ │ ├── .gitignore
│ │ ├── .travis.yml
│ │ ├── AUTHORS
│ │ ├── HISTORY
│ │ ├── INSTALL
│ │ ├── LICENSE
│ │ ├── Makefile
│ │ ├── README
│ │ ├── benchmark.cc
│ │ ├── benchmark.geany
│ │ ├── benchmark.sln
│ │ ├── benchmark.vcxproj
│ │ ├── benchmark
│ │ │ ├── gr_all.bat
│ │ │ ├── gr_all.sh
│ │ │ ├── gr_common.gnu
│ │ │ ├── gr_def_random_change.gnu
│ │ │ ├── gr_def_random_hit.gnu
│ │ │ ├── gr_forward_change.gnu
│ │ │ ├── gr_forward_hit.gnu
│ │ │ ├── gr_forward_insert.gnu
│ │ │ ├── gr_forward_miss.gnu
│ │ │ ├── gr_forward_remove.gnu
│ │ │ ├── gr_forward_size.gnu
│ │ │ ├── gr_other_ck_problem.gnu
│ │ │ ├── gr_other_googlelibchash_problem.gnu
│ │ │ ├── gr_other_judy_problem.gnu
│ │ │ ├── gr_random_change.gnu
│ │ │ ├── gr_random_hit.gnu
│ │ │ ├── gr_random_insert.gnu
│ │ │ ├── gr_random_miss.gnu
│ │ │ ├── gr_random_remove.gnu
│ │ │ └── gr_random_size.gnu
│ │ ├── check.c
│ │ ├── makecov.sh
│ │ ├── makescan.sh
│ │ ├── tommy-footer.html
│ │ ├── tommy-header.html
│ │ ├── tommy.css
│ │ ├── tommy.doxygen
│ │ ├── tommyds
│ │ │ ├── tommy.c
│ │ │ ├── tommy.h
│ │ │ ├── tommyalloc.c
│ │ │ ├── tommyalloc.h
│ │ │ ├── tommyarray.c
│ │ │ ├── tommyarray.h
│ │ │ ├── tommyarrayblk.c
│ │ │ ├── tommyarrayblk.h
│ │ │ ├── tommyarrayblkof.c
│ │ │ ├── tommyarrayblkof.h
│ │ │ ├── tommyarrayof.c
│ │ │ ├── tommyarrayof.h
│ │ │ ├── tommychain.h
│ │ │ ├── tommyhash.c
│ │ │ ├── tommyhash.h
│ │ │ ├── tommyhashdyn.c
│ │ │ ├── tommyhashdyn.h
│ │ │ ├── tommyhashlin.c
│ │ │ ├── tommyhashlin.h
│ │ │ ├── tommyhashtbl.c
│ │ │ ├── tommyhashtbl.h
│ │ │ ├── tommylist.c
│ │ │ ├── tommylist.h
│ │ │ ├── tommytree.c
│ │ │ ├── tommytree.h
│ │ │ ├── tommytrie.c
│ │ │ ├── tommytrie.h
│ │ │ ├── tommytrieinp.c
│ │ │ ├── tommytrieinp.h
│ │ │ └── tommytypes.h
│ │ ├── tommyweb-header.html
│ │ └── tommyweb.doxygen
│ └── types.h
└── weaver.h
├── rubik
├── __init__.py
├── __main__.py
├── compile.py
├── compile2.py
├── lang.py
├── prog.py
└── util.py
└── stock
├── __init__.py
├── gtp.py
├── pptp.py
├── protocols
├── __init__.py
├── eth.py
├── gre.py
├── gtp.py
├── ip.py
├── loopback.py
├── ppp.py
├── pptp.py
├── quic_frame.py
├── quic_header.py
├── quic_udp.py
├── sctp.py
├── tcp.py
└── udp.py
├── quic.py
├── sctp.py
└── tcp_ip.py
/.gitattributes:
--------------------------------------------------------------------------------
1 | native/runtime/tommyds/* linguist-vendored
2 | app/http-parser/* linguist-vendored
3 | app/libac/* linguist-vendored
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 |
131 |
132 | pcap/
133 | weaver_whitebox.c
134 | *.cfg
135 | stack.py
136 | *_test
137 | *.snapshot
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "gcc - Build and debug active file",
9 | "type": "cppdbg",
10 | "request": "launch",
11 | "program": "${fileDirname}/${fileBasenameNoExtension}",
12 | "args": [],
13 | "stopAtEntry": false,
14 | "cwd": "${workspaceFolder}",
15 | "environment": [],
16 | "externalConsole": false,
17 | "MIMode": "gdb",
18 | "setupCommands": [
19 | {
20 | "description": "Enable pretty-printing for gdb",
21 | "text": "-enable-pretty-printing",
22 | "ignoreFailures": true
23 | }
24 | ],
25 | "preLaunchTask": "C/C++: gcc build active file",
26 | "miDebuggerPath": "/usr/bin/gdb"
27 | }
28 | ]
29 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "python.pythonPath": "./env/bin/python3.7",
3 | "python.formatting.provider": "black",
4 | "C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: LLVM, ContinuationIndentWidth: 2, AlignAfterOpenBracket: AlwaysBreak, BinPackArguments: false }"
5 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "tasks": [
3 | {
4 | "type": "shell",
5 | "label": "C/C++: gcc build active file",
6 | "command": "/usr/bin/gcc",
7 | "args": [
8 | "-g",
9 | "${file}",
10 | "-o",
11 | "${fileDirname}/${fileBasenameNoExtension}"
12 | ],
13 | "options": {
14 | "cwd": "${workspaceFolder}"
15 | },
16 | "problemMatcher": [
17 | "$gcc"
18 | ],
19 | "group": {
20 | "kind": "build",
21 | "isDefault": true
22 | }
23 | }
24 | ],
25 | "version": "2.0.0"
26 | }
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 |
3 |
4 | A ?= weaver_whitebox.c
5 | T ?= pcap
6 | C ?= stack_conf
7 | bb := weaver_blackbox.c
8 | wb := weaver_whitebox.template.c
9 | sep = Weaver Auto-generated Blackbox Code
10 |
11 | BUILD_DIR = ./build/
12 | APP = procpkts
13 | TARGET_FLAG = -DWV_TARGET_$(T)
14 | export TARGET_FLAG
15 |
16 | ### GCC ###
17 | GCC = gcc
18 | GCC_OPT = -m64 # -Wall -DNEWEV -Werror
19 |
20 | GCC_OPT += -g -DNETSTAT -DINFO -DDBGERR -DDBGCERR
21 | # GCC_OPT += -O3 -DNDEBUG -DNETSTAT -DINFO -DDBGERR -DDBGCERR
22 | GCC_OPT += $(DBG_OPT)
23 |
24 | ### LIBRARIES AND INCLUDES ###
25 | INC_DIR = ./native
26 | INC= -I$(INC_DIR) -I$(INC_DIR)/runtime -I$(INC_DIR)/runtime/tommyds
27 |
28 | ### SOURCE FILES ###
29 |
30 | LIB_FLAGS += -lstdc++ -lpcre2-8
31 | ifeq ($(T), pcap)
32 | LIB_FLAGS += -lpcap
33 | endif
34 |
35 | ifeq ($(T), dpdk)
36 | ifeq ($(RTE_SDK),)
37 | $(error "Please define RTE_SDK environment variable")
38 | endif
39 | RTE_TARGET ?= x86_64-native-linuxapp-gcc
40 |
41 | NIC ?= XL710
42 | FWD ?= FWD
43 | PERF ?= EVAL_PERF
44 | SRC_DIR = $(PWD)
45 | SRCS = $(bb) $(A) native/drivers/$(T).c $(SRC_DIR)/native/runtime/libwvrt.a
46 | DPDK_INC = -I$(SRC_DIR)/native/ -I$(SRC_DIR)/native/runtime -I$(SRC_DIR)/native/runtime/tommyds
47 | include $(RTE_SDK)/mk/rte.vars.mk
48 | CFLAGS += $(DPDK_INC) -D$(NIC) -D$(PERF) $(GCC_OPT) -D$(FWD)
49 | LDFLAGS += -lpcre2-8
50 |
51 | SRCS-y := $(SRCS)
52 | include $(RTE_SDK)/mk/rte.extapp.mk
53 |
54 | $(SRC_DIR)/native/runtime/libwvrt.a:
55 | cd $(SRC_DIR)/native/runtime && $(MAKE) -C .
56 |
57 | endif
58 |
59 | ifeq ($(T), pcap)
60 | ### GOALS ###
61 | SRCS = $(bb) $(A) native/drivers/$(T).c native/runtime/libwvrt.a
62 |
63 | all: $(APP)
64 |
65 | $(APP): $(SRCS)
66 | $(GCC) $(GCC_OPT) -o $@ $^ $(INC) $(LIBS) $(LIB_FLAGS) $(TARGET_FLAG)
67 |
68 | native/runtime/libwvrt.a:
69 | $(MAKE) -C native/runtime
70 |
71 | clean:
72 | -$(RM) procpkts $(wb) $(bb)
73 | -$(RM) -rf build/
74 | -$(RM) native/weaver.h.gch
75 | -$(RM) test_seq
76 | $(MAKE) -C native/runtime clean
77 |
78 | .PHONY: all clean weaver_blackbox.c native/runtime/libwvrt.a
79 | endif
80 |
81 | gen:
82 | # https://stackoverflow.com/a/7104422
83 | python3 -m rubik $(C) | tee >(sed -e "/$(sep)/,\$$d" > $(wb)) | sed -n -e "/$(sep)/,\$$w $(bb)"
84 |
85 | test: test_seq
86 | ./test_seq
87 |
88 | test_seq: native/runtime/seq_test.c native/runtime/seq.h
89 | $(GCC) -o test_seq native/runtime/seq_test.c
90 |
--------------------------------------------------------------------------------
/Makefile_DPDK:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 |
3 |
4 | A ?= weaver_whitebox.c
5 | C ?= stack_conf
6 | T ?= dpdk
7 | bb := weaver_blackbox.c
8 | wb := weaver_whitebox.template.c
9 | sep = Weaver Auto-generated Blackbox Code
10 |
11 | BUILD_DIR = ./build/
12 | APP = procpkts
13 | TARGET_FLAG = -DWV_TARGET_$(T)
14 | export TARGET_FLAG
15 |
16 | ### GCC ###
17 | GCC = gcc
18 | GCC_OPT = -m64 # -Wall -DNEWEV -Werror
19 |
20 | GCC_OPT += -g -DNETSTAT -DINFO -DDBGERR -DDBGCERR
21 | # GCC_OPT += -O3 -DNDEBUG -DNETSTAT -DINFO -DDBGERR -DDBGCERR
22 | GCC_OPT += $(DBG_OPT)
23 |
24 | ### LIBRARIES AND INCLUDES ###
25 | INC_DIR = ./native
26 | INC= -I$(INC_DIR) -I$(INC_DIR)/runtime -I$(INC_DIR)/runtime/tommyds
27 |
28 | ### SOURCE FILES ###
29 |
30 | # Build using pkg-config variables if possible
31 | ifneq ($(shell pkg-config --exists libdpdk && echo 0),0)
32 | $(error "no installation of DPDK found")
33 | endif
34 |
35 | LIB_FLAGS += -lstdc++ -lpcre2-8
36 |
37 | all: shared
38 | .PHONY: shared static
39 | shared: build/$(APP)-shared
40 | ln -sf $(APP)-shared build/$(APP)
41 | static: build/$(APP)-static
42 | ln -sf $(APP)-static build/$(APP)
43 |
44 | PKGCONF ?= pkg-config
45 |
46 | PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
47 | CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
48 | # Add flag to allow experimental API as l2fwd uses rte_ethdev_set_ptype API
49 | CFLAGS += -DALLOW_EXPERIMENTAL_API
50 | LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
51 | LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
52 |
53 | ifeq ($(MAKECMDGOALS),static)
54 | # check for broken pkg-config
55 | ifeq ($(shell echo $(LDFLAGS_STATIC) | grep 'whole-archive.*l:lib.*no-whole-archive'),)
56 | $(warning "pkg-config output list does not contain drivers between 'whole-archive'/'no-whole-archive' flags.")
57 | $(error "Cannot generate statically-linked binaries with this version of pkg-config")
58 | endif
59 | endif
60 |
61 |
62 | SRC_DIR = $(PWD)
63 | SRCS = $(bb) $(A) native/drivers/$(T).c $(SRC_DIR)/native/runtime/libwvrt.a
64 | DPDK_INC = -I$(SRC_DIR)/native/ -I$(SRC_DIR)/native/runtime -I$(SRC_DIR)/native/runtime/tommyds
65 | CFLAGS += $(DPDK_INC) $(GCC_OPT)
66 | # LDFLAGS += -lpcre2-8
67 |
68 | SRCS-y := $(SRCS)
69 |
70 | $(SRC_DIR)/native/runtime/libwvrt.a:
71 | cd $(SRC_DIR)/native/runtime && $(MAKE) -C .
72 |
73 |
74 | gen:
75 | # https://stackoverflow.com/a/7104422
76 | python3 -m rubik $(C) | tee >(sed -e "/$(sep)/,\$$d" > $(wb)) | sed -n -e "/$(sep)/,\$$w $(bb)"
77 |
78 | test: test_seq
79 | ./test_seq
80 |
81 | test_seq: native/runtime/seq_test.c native/runtime/seq.h
82 | $(GCC) -o test_seq native/runtime/seq_test.c
83 |
84 | build/$(APP)-shared: $(SRCS-y) Makefile_DPDK $(PC_FILE) | build
85 | $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) $(TARGET_FLAG)
86 |
87 | build/$(APP)-static: $(SRCS-y) Makefile_DPDK $(PC_FILE) | build
88 | $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) $(TARGET_FLAG)
89 |
90 | build:
91 | @mkdir -p $@
92 |
93 | .PHONY: clean
94 | clean:
95 | rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
96 | test -d build && rmdir -p build || true
97 | -$(RM) procpkts $(wb) $(bb)
98 | -$(RM) -rf build/
99 | -$(RM) native/weaver.h.gch
100 | -$(RM) test_seq
101 | $(MAKE) -C native/runtime clean
--------------------------------------------------------------------------------
/Makefile_PCAP:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 |
3 | A ?= weaver_whitebox.c
4 | T ?= pcap
5 | C ?= stack_conf
6 | bb := weaver_blackbox.c
7 | wb := weaver_whitebox.template.c
8 | sep = Weaver Auto-generated Blackbox Code
9 |
10 | BUILD_DIR = ./build/
11 | APP = procpkts
12 | TARGET_FLAG = -DWV_TARGET_$(T)
13 | export TARGET_FLAG
14 |
15 | ### GCC ###
16 | GCC = gcc
17 | GCC_OPT = -m64 # -Wall -DNEWEV -Werror
18 |
19 | GCC_OPT += -g -DNETSTAT -DINFO -DDBGERR -DDBGCERR
20 | # GCC_OPT += -O3 -DNDEBUG -DNETSTAT -DINFO -DDBGERR -DDBGCERR
21 | GCC_OPT += $(DBG_OPT)
22 |
23 | ### LIBRARIES AND INCLUDES ###
24 | INC_DIR = ./native
25 | INC= -I$(INC_DIR) -I$(INC_DIR)/runtime -I$(INC_DIR)/runtime/tommyds
26 |
27 | ### SOURCE FILES ###
28 |
29 | LIB_FLAGS += -lstdc++ -lpcre2-8
30 | ifeq ($(T), pcap)
31 | LIB_FLAGS += -lpcap
32 | endif
33 |
34 |
35 | ifeq ($(T), pcap)
36 | ### GOALS ###
37 | SRCS = $(bb) $(A) native/drivers/$(T).c native/runtime/libwvrt.a
38 |
39 | all: $(APP)
40 |
41 | $(APP): $(SRCS)
42 | $(GCC) $(GCC_OPT) -o $@ $^ $(INC) $(LIBS) $(LIB_FLAGS) $(TARGET_FLAG)
43 |
44 | native/runtime/libwvrt.a:
45 | $(MAKE) -C native/runtime
46 |
47 | clean:
48 | -$(RM) procpkts $(wb) $(bb)
49 | -$(RM) -rf build/
50 | -$(RM) native/weaver.h.gch
51 | -$(RM) test_seq
52 | $(MAKE) -C native/runtime clean
53 |
54 | .PHONY: all clean weaver_blackbox.c native/runtime/libwvrt.a
55 | endif
56 |
57 | gen:
58 | # https://stackoverflow.com/a/7104422
59 | python3 -m rubik $(C) | tee >(sed -e "/$(sep)/,\$$d" > $(wb)) | sed -n -e "/$(sep)/,\$$w $(bb)"
60 |
61 | test: test_seq
62 | ./test_seq
63 |
64 | test_seq: native/runtime/seq_test.c native/runtime/seq.h
65 | $(GCC) -o test_seq native/runtime/seq_test.c
66 |
--------------------------------------------------------------------------------
/Makefile_deprecated:
--------------------------------------------------------------------------------
1 | SHELL := /bin/bash
2 |
3 |
4 | A ?= weaver_whitebox.c
5 | T ?= pcap
6 | C ?= stack_conf
7 | bb := weaver_blackbox.c
8 | wb := weaver_whitebox.template.c
9 | sep = Weaver Auto-generated Blackbox Code
10 |
11 | BUILD_DIR = ./build/
12 | APP = procpkts
13 | TARGET_FLAG = -DWV_TARGET_$(T)
14 | export TARGET_FLAG
15 |
16 | ### GCC ###
17 | GCC = gcc
18 | GCC_OPT = -m64 # -Wall -DNEWEV -Werror
19 |
20 | GCC_OPT += -g -DNETSTAT -DINFO -DDBGERR -DDBGCERR
21 | # GCC_OPT += -O3 -DNDEBUG -DNETSTAT -DINFO -DDBGERR -DDBGCERR
22 | GCC_OPT += $(DBG_OPT)
23 |
24 | ### LIBRARIES AND INCLUDES ###
25 | INC_DIR = ./native
26 | INC= -I$(INC_DIR) -I$(INC_DIR)/runtime -I$(INC_DIR)/runtime/tommyds
27 |
28 | ### SOURCE FILES ###
29 |
30 | LIB_FLAGS += -lstdc++ -lpcre2-8
31 | ifeq ($(T), pcap)
32 | LIB_FLAGS += -lpcap
33 | endif
34 |
35 | ifeq ($(T), dpdk)
36 | ifeq ($(RTE_SDK),)
37 | $(error "Please define RTE_SDK environment variable")
38 | endif
39 | RTE_TARGET ?= x86_64-native-linuxapp-gcc
40 |
41 | SRC_DIR = $(PWD)
42 | SRCS = $(bb) $(A) native/drivers/$(T).c $(SRC_DIR)/native/runtime/libwvrt.a
43 | DPDK_INC = -I$(SRC_DIR)/native/ -I$(SRC_DIR)/native/runtime -I$(SRC_DIR)/native/runtime/tommyds
44 | include $(RTE_SDK)/mk/rte.vars.mk
45 | CFLAGS += $(DPDK_INC) -D$(NIC) -D$(PERF) $(GCC_OPT) -D$(FWD)
46 | LDFLAGS += -lpcre2-8
47 |
48 | SRCS-y := $(SRCS)
49 | include $(RTE_SDK)/mk/rte.extapp.mk
50 |
51 | $(SRC_DIR)/native/runtime/libwvrt.a:
52 | cd $(SRC_DIR)/native/runtime && $(MAKE) -C .
53 |
54 | endif
55 |
56 | ifeq ($(T), pcap)
57 | ### GOALS ###
58 | SRCS = $(bb) $(A) native/drivers/$(T).c native/runtime/libwvrt.a
59 |
60 | all: $(APP)
61 |
62 | $(APP): $(SRCS)
63 | $(GCC) $(GCC_OPT) -o $@ $^ $(INC) $(LIBS) $(LIB_FLAGS) $(TARGET_FLAG)
64 |
65 | native/runtime/libwvrt.a:
66 | $(MAKE) -C native/runtime
67 |
68 | clean:
69 | -$(RM) procpkts $(wb) $(bb)
70 | -$(RM) -rf build/
71 | -$(RM) native/weaver.h.gch
72 | -$(RM) test_seq
73 | $(MAKE) -C native/runtime clean
74 |
75 | .PHONY: all clean weaver_blackbox.c native/runtime/libwvrt.a
76 | endif
77 |
78 | gen:
79 | # https://stackoverflow.com/a/7104422
80 | python3 -m rubik $(C) | tee >(sed -e "/$(sep)/,\$$d" > $(wb)) | sed -n -e "/$(sep)/,\$$w $(bb)"
81 |
82 | test: test_seq
83 | ./test_seq
84 |
85 | test_seq: native/runtime/seq_test.c native/runtime/seq.h
86 | $(GCC) -o test_seq native/runtime/seq_test.c
87 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Proof-of-concept and evaluation prototype for NSDI'21: *Programming Network Stack for Middleboxes with Rubik*
2 |
3 | Step 0, make sure `python3` installed with version >= 3.7; C toolchain (e.g. `build-essential` on Ubuntu) installed; `libpcap-dev` is required for `pcap` target and DPDK SDK is required for `dpdk` target. And mako package is installed:
4 |
5 | ```
6 | pip3 install mako
7 | ```
8 |
9 | Step 1, generate `weaver_blackbox.c` according to configure
10 |
11 | ```
12 | # to build stocking protocol stacks
13 | make gen C=stock.tcp_ip
14 | make gen C=stock.gtp
15 | ```
16 |
17 | Step 2, compile the blackbox along with custom code
18 |
19 | ```
20 | # auto-generated blank template
21 | make A=weaver_whitebox.template.c
22 | # generally it's recommend to edit the copy of the template
23 | cp weaver_whitebox.template.c weaver_whitebox.c
24 | # and build it with custom code
25 | make
26 | # DPDK target
27 | make T=dpdk
28 | ```
29 |
30 | Finally, run built executable `procpkts`.
31 |
32 | ----
33 |
34 | Rubik is a perfect tool for:
35 | * building software middlebox for network stacks, e.g. TCP/IP, GTP, QUIC
36 | * validating the functionality of newly-designed protocols
37 | * modeling network protocols/stacks with a comprehensive abstraction
38 |
39 | To learn more, please head on to [a tour of Rubik](./doc/00-a-tour-of-rubik.markdown) and enjoy hacking!
40 |
--------------------------------------------------------------------------------
/doc/01-layout-and-header-stage.markdown:
--------------------------------------------------------------------------------
1 | > Author: Sun Guangda \
2 | > Date: 2020.9.29
3 |
4 | This is the catch-up document for layout declaration and header stage. You have learned the basic usage of them in [the tour](doc/00-a-tour-of-rubik.markdown).
5 |
6 | #### Variable-length field
7 |
8 | Variable-length fields are fields that cannot determine length until runtime. There must exist an expression that only depends on the values of fields **occur before this field** and whose value is the **bit length** of this field. A common case of variable-length field is an IP option, whose value field always follows a single-byte length field to record the byte length of it. It could be declared as a layout like:
9 |
10 | ```python
11 | class ip_option(layout):
12 | length = Bit(8)
13 | value = Bit(length << 3)
14 | ```
15 |
16 | Variable-length fields always have byte slice type.
17 |
18 | #### Declare layout for permanent variables
19 |
20 | Every permanent variable must have an initial value, which will be used if the instance is just created. The initial value can be any expression that only depends on header fields, and it is indicated with `init` property:
21 |
22 | ```python
23 | class tcp_perm_vars(layout):
24 | window_left = Bit(32, init=0)
25 | window_right = Bit(32, init=(1 << 32) - 1)
26 | ```
27 |
28 | #### Sequence parsing
29 |
30 | You can use `+` to connect layouts to parse them sequentially:
31 |
32 | ```python
33 | myproto.header = mylayout1 + mylayout2
34 | ```
35 |
36 | #### Conditional parsing
37 |
38 | You can use `If` statement to parse a layout base on some conditions. The condition could be an expression that depends on header fields that already parsed when encountering the condition.
39 |
40 | ```python
41 | myproto.header = mylayout1 + If(mylayout1.has_layout2 == 1) >> mylayout2 # myproto.header.has_layout2 is also available
42 | ```
43 |
44 | Unlike preparation stage, `Else` syntax is not impemented here. There's also a bug currently occuring if you assign `If` statement to a Python name and then reference to that name in header stage assignment, so just prevent to do it for now.
45 |
46 | #### Options-parsing loop
47 |
48 | It is an idiomatic way to design protocol header with variable-number, variable-length optional fields as type-length-variable (TLV). Rubik provides a handy way to define it.
49 |
50 | First, declare each of all types of value a layout. The type field of them must appear at the beginning of the layout and have the same length:
51 |
52 | ```python
53 | class optional_timestamp(layout):
54 | type = Bit(8, const=6) # use `const` property to declare type number
55 | timestamp = UInt(32)
56 |
57 | class optional_flags(layout):
58 | type = Bit(8, const=13)
59 | flag_a = Bit(1)
60 | flag_b = Bit(4)
61 | _reserved = Bit(3)
62 |
63 | class optional_string(layout):
64 | type = Bit(8, const=25)
65 | length = Bit(8)
66 | string = Bit(length << 3)
67 |
68 | class optional_others(layout):
69 | type = Bit(8) # fallback case
70 | length = Bit(8)
71 | remain = Bit(length << 3)
72 |
73 | class end_of_options(layout):
74 | type = Bit(8, const=0)
75 | ```
76 |
77 | A fallback case is useful if any of option types we don't care have the same layout. Note that the content of layout (corresponding struct in C) of the fallback case will be override multiple times, so its content is garbage, so you have to define a `optional_string` layout even it has the exact same fields as the fallback layout, since you care about its content rather than just skip it.
78 |
79 | An `AnyUntil` statement could be used in header stage with all the option layouts:
80 |
81 | ```python
82 | myproto.header = AnyUntil([
83 | optional_timestamp,
84 | optional_flags,
85 | optional_string,
86 | optional_others,'
87 | end_of_options,
88 | ], myproto.header.type == 0)
89 | ```
90 |
91 | This will generate a `while` loop with a `switch` statement inside, which fill all the layouts of the appeared options. Every option type could only present once in the packet, or the packet will be treated as malformed and the processing will be terminated.
92 |
--------------------------------------------------------------------------------
/doc/02-expression-and-variable.markdown:
--------------------------------------------------------------------------------
1 | > Author: Sun Guangda \
2 | > Date: 2020.9.30
3 |
4 | This is the catch-up document for expressions and variables in Rubik. Expressions could appear in:
5 | * length expression of variable-length field
6 | * condition in header stage
7 | * preparation statement
8 | * sequence property
9 | * prediction and action statement in PSM stage
10 | * condition and action statement in event stage
11 | * layer entry condition
12 |
13 | The "statement" above only includes two types: `If`-`Else` block and `Assign` statement, and the latter one make an assignment of the value of an expression to a variable. Notice that there's one place which suprisingly do not allowed expression: instance selector definition. It must be a list or a tuple of two lists which only contains plain header fields.
14 |
15 | #### Expression and variable type
16 |
17 | There are two variable types in Rubik: number type and byte slice type. Number type includes fixed fields of all full-byte length and also bit fields. Byte slice type is implemented as a tuple composed by a pointer to the head byte of buffer and a length field, which is the same as Rust's built-in `&[u8]` slice type. Byte slice is technically a "byte slice view", which does not own any data by itself. All byte slices created in a layer configure are either a part of packet or empty slice. As a result, all slices share the same underlaying buffer and there's no modifying opertor defined for them.
18 |
19 | Each expression also has a type. Constant number has number type and constant empty slice has slice type. Expressions that simply read a variable have the same type as read variable. The type of expression decides which set of operators are defined on it. For a number expression, you can:
20 | * operate `+`, `-`, `<<`, `>>` with another number-typed expression as the right-hand operand, and the result expression has number type
21 | * operate `==`, `!=` with another number-typed expression as the right-hand operand, or use `NotOp(expr)` which is an unary operator, and the result expression has number type (`0` for false and `1` for true)
22 | * operate `&`, `|` with anumber number-typed expression as the right-head operand, which has two cases:
23 | * if the left-hand expression is a variable, these are bitwise operators
24 | * if the left-hand expression is compound expression, these are logical operators
25 |
26 | Both cases result an number-typed expression.
27 |
28 | For a slice expression, you can:
29 | * operate `[a:b]` where `a` and `b` are number-typed expressions to shorten the slice from two sides, and the result is a slice
30 | * operate `[i]` where `i` is number-typed expression to extract a byte from slice, and the result is a number
31 | * access read-only property `.length` to get the length of the slice, and the result is a number
32 |
33 | Adding custom operators to number and slice types are quite easy. The corresponding document will be released once the related interface is stable.
34 |
35 | #### Built-in variables
36 |
37 | There are a few variables provided by Rubik runtime which is useful on centain stages and cases.
38 | * `payload` is the *unparsed* part of the packet, which may keep changing in header stage
39 | * `cursor` is the length of parsed part by current layer of the packet
40 | * `sdu` equals to `payload` if `Assemble` statement is not executed, and stores the result of `Assemble` statement
41 | * `current_state` is the index of current state in PSM, the state corresponds to current packet in event stage and corresoponds to previous packet (or start state if no previous packet) before event stage
42 | * `to_active` and `to_passive` indicate the direction of current packet, currently they are implemented as expression
43 |
44 | You should never assign to these variables.
45 |
46 | #### Virtual expression
47 |
48 | The concept of virtual expression is shown in the tour. Internally Rubik create a permanent variable for each virtual expression to record that if the expression "has been" true for any past packet (including current one), and virtual expression will be true if both and permanent variable is set and sequence has no unsorted fragment (there no "hole" in recived buffer). Thus you must define instance and sequence stage if you want to use virtual expression.
49 |
50 | A simple virtual expression is easy to understand, for example, `sp.v.header.x == 1` means "a packet with x field set to 1 has been seen and sequence is sorted". However, things get complicated when virtual expressions are compounded with boolean operators. With negating operator, `NotOp(sp.v.header.x == 1)` means "the expected packet has not been seen or the sequence is still unsorted", which has a different meaning with `sp.v.header.x != 1`. With logical and expression, `sp.v.header.x == 1 & sp.v.header.y == 1` means "both flags has been seen to be set **in the same packet**, and the sequence is sorted now". The internal permanent variable is actually tracking expression `sp.header.x == 1 & sp.header.y == 1`, which means virtual expressions *extend* across logical and operators. So the expression is equivalent to `sp.v.header.x == 1 & sp.header.y == 1`, but it's less obvious to write in this way. In one word, virtual expressions extend across logical and, but not extend across logical or and logical not operators. If you really need the semantic different from virtual expression's behaviour, try to desugar the code and use permanent variable directly.
--------------------------------------------------------------------------------
/doc/03-semantic-completeness.markdown:
--------------------------------------------------------------------------------
1 | | NF | Description | Can Rubik help development? | How can Rubik support it/Why does Rubik not support it |
2 | | ------------------------------------------------------------ | --------------------------------------------------------- | --------------------------- | ------------------------------------------------------------ |
3 | | Stateless Firewall | Reject traffic from certain hosts/ports | Yes | **Rubik**: pose the 5-tuple of each packet to the high-level function
**High-level function**: match the 5-tuple and reject the traffic |
4 | | Stateful Firewall | Reject the adversaries with half-connection attacks | Yes | **Rubik**: raise an event of the first and the third handshake of each TCP connection, and pose the connection information to the high-level function.
**High-level function**: Upon the first handshake, maintaining a list that records every newly-recevied SYN and expires those that times out. SYN from the expired host will be dropped for some time; Upon the third handshake, removing the host from list |
5 | | IDS | Detect malicious content in traffic | Yes | **Rubik**: pose the reassembled payload to high-level function
**High-level function**: match the payload against a set of rules |
6 | | NAT | Rewrite packet header between LAN and WAN | Yes | **Rubik**: pose the source and destination IP address and their pointers of each IP packet to high-level function
**High-level function**: maintain a hash table storing the active mapping from LAN IP address to WAN IP address, rewrite the header of each packet according to the mappings |
7 | | IPS | Prevent attack on detecting malicious content | No | **Rubik**: pose the reassembled payload to high-level function
**High-level function**: the packets have been sent out when the high-level function can inspect. Therefore, the NF cannot modify or drop the packet |
8 | | HTTP proxy | Proxy/filter HTTP traffic | No | **Rubik**: pose the reassembled payload to high-level function
**High-level function**: The NF can modify L2-L4 header to proxy the traffic, but cannot filter L7 content, e.g. remove ads |
9 | | Inline stream edit [MiddleClick](https://www.diva-portal.org/smash/record.jsf?dswid=1144&pid=diva2%3A1582880&c=1&searchType=SIMPLE&language=en&query=Combined+stateful+classification+and+session+splicing+for+high-speed+NFV+service+chaining&af=%5B%5D&aq=%5B%5B%5D%5D&aq2=%5B%5B%5D%5D&aqe=%5B%5D&noOfRows=50&sortOrder=author_sort_asc&sortOrder2=title_sort_asc&onlyFullText=false&sf=all) | Prevent forwarding packets before stream data is modified | No | **Rubik**: To make the sender keep sending packets, the NF must proactively send ACK to collect enough data. However, Rubik currently does not support sending packets |
10 |
11 |
--------------------------------------------------------------------------------
/doc/04-peephole-optimizations.markdown:
--------------------------------------------------------------------------------
1 | 
--------------------------------------------------------------------------------
/doc/04-peephole-optimizations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ants-xjtu/rubik/107cc58254f56c02902f55c2b87054f5ebfcd502/doc/04-peephole-optimizations.png
--------------------------------------------------------------------------------
/native/drivers/pcap.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | WV_U8 ctrl_c = 0;
10 |
11 | void ctrl_c_handler(int sig) {
12 | if (ctrl_c) {
13 | printf("shut down badly\n");
14 | exit(1);
15 | }
16 | printf("\nwill shut down (ctrl-c again to kill)\n");
17 | ctrl_c = 1;
18 | }
19 |
20 | typedef struct {
21 | WV_Runtime *runtime;
22 | pcap_t *pcap;
23 | } PcapUser;
24 |
25 | void proc(WV_Byte *user, const struct pcap_pkthdr *pcap_header, const WV_Byte *pcap_data) {
26 | WV_Runtime *runtime = ((PcapUser *)user)->runtime;
27 | WV_ByteSlice packet = { .cursor = pcap_data, .length = pcap_header->len };
28 | WV_U8 status = WV_ProcessPacket(packet, runtime);
29 | WV_ProfileRecord(WV_GetProfile(runtime), pcap_header->len, status);
30 | if (ctrl_c) {
31 | pcap_breakloop(((PcapUser *)user)->pcap);
32 | }
33 | }
34 |
35 | int main(int argc, char *argv[]) {
36 | char *pcap_filename = NULL;
37 | WV_U8 no_loop = 0;
38 | for (int i = 1; i < argc; i += 1) {
39 | if (strcmp(argv[i], "--noloop") == 0) {
40 | no_loop = 1;
41 | } else {
42 | pcap_filename = argv[i];
43 | }
44 | }
45 | if (pcap_filename == NULL) {
46 | printf("no pcap file\n");
47 | return 0;
48 | }
49 |
50 | WV_Runtime *runtime;
51 | if (!(runtime = WV_AllocRuntime())) {
52 | fprintf(stderr, "runtime initialization fail\n");
53 | return 1;
54 | }
55 |
56 | char errbuf[PCAP_ERRBUF_SIZE];
57 | pcap_t *pcap_packets = pcap_open_offline(pcap_filename, errbuf);
58 | if (!pcap_packets) {
59 | fprintf(stderr, "pcap_open_offline: %s\n", errbuf);
60 | return 1;
61 | }
62 |
63 | PcapUser user = { .runtime = runtime, .pcap = pcap_packets };
64 |
65 | signal(SIGINT, ctrl_c_handler);
66 | WV_Setup();
67 | WV_ProfileStart(WV_GetProfile(runtime));
68 | for (;;) {
69 | pcap_loop(pcap_packets, -1, proc, (void *)&user);
70 | pcap_close(pcap_packets);
71 | if (ctrl_c || no_loop) {
72 | break;
73 | }
74 | pcap_packets = pcap_open_offline(pcap_filename, errbuf);
75 | if (!pcap_packets) {
76 | fprintf(stderr, "pcap_open_offline: %s\n", errbuf);
77 | return 1;
78 | }
79 | }
80 |
81 | WV_ProfileRecordPrint(WV_GetProfile(runtime));
82 | if (WV_FreeRuntime(runtime)) {
83 | fprintf(stderr, "runtime cleanup fail\n");
84 | return 1;
85 | }
86 |
87 | printf("shut down correctly\n");
88 |
89 | return 0;
90 | }
--------------------------------------------------------------------------------
/native/runtime/Makefile:
--------------------------------------------------------------------------------
1 | all: libwvrt.a
2 |
3 | libwvrt.a: profile.o tommyds/tommy.o
4 | $(AR) rc $@ $^
5 |
6 | tommyds/tommy.o:
7 | $(MAKE) -C tommyds
8 |
9 | %.o: %.c %.h types.h
10 | $(CC) -c -g -O3 $< -I./tommyds $(TARGET_FLAG)
11 |
12 | clean:
13 | -$(RM) libwvrt.a
14 | -$(RM) *.o *.gch
15 | -$(MAKE) -C tommyds clean
16 |
17 | .PHONY: all clean
18 |
--------------------------------------------------------------------------------
/native/runtime/malloc.h:
--------------------------------------------------------------------------------
1 | #ifndef WEAVER_RUNTIME_MALLOC_H
2 | #define WEAVER_RUNTIME_MALLOC_H
3 |
4 | #ifdef WV_TARGET_dpdk
5 | #include
6 | #include
7 | #define WV_Malloc(n) rte_malloc(NULL, n, 0)
8 | #define WV_Free rte_free
9 | #define WV_Memcpy rte_memcpy
10 | #else
11 | #include
12 | #include
13 | #define WV_Malloc malloc
14 | #define WV_Free free
15 | #define WV_Memcpy memcpy
16 | #endif
17 |
18 | #endif
--------------------------------------------------------------------------------
/native/runtime/profile.c:
--------------------------------------------------------------------------------
1 | #include "profile.h"
2 | #include
3 | #include
4 | #include
5 |
6 | WV_U8 WV_ProfileStart(WV_Profile* profile)
7 | {
8 | memset(profile, 0, sizeof(WV_Profile));
9 | WV_F current = clock() / CLOCKS_PER_SEC;
10 | profile->last_record_sec = current;
11 | profile->next_checkpoint_sec = (WV_U32)current + 1;
12 | }
13 |
14 | WV_U8 WV_ProfileRecord(WV_Profile* profile, WV_U32 byte_length, WV_U8 status)
15 | {
16 | // TODO: use status
17 | profile->interval_byte_count += byte_length;
18 | profile->interval_packet_count += 1;
19 | if (profile->interval_packet_count % 1000000 != 0) {
20 | return 0;
21 | }
22 | WV_F current = (WV_F)clock() / CLOCKS_PER_SEC;
23 | if (current < profile->next_checkpoint_sec) {
24 | return 0;
25 | }
26 |
27 | WV_ProfileRecordPrint(profile);
28 |
29 | profile->interval_byte_count = 0;
30 | profile->interval_packet_count = 0;
31 | profile->next_checkpoint_sec = (WV_U32)current + 2;
32 | profile->last_record_sec = current;
33 | return 0;
34 | }
35 |
36 | WV_U8 WV_ProfileRecordPrint(WV_Profile* profile)
37 | {
38 | WV_F current = (WV_F)clock() / CLOCKS_PER_SEC;
39 | WV_F interval = current - profile->last_record_sec;
40 | WV_F throughput = profile->interval_byte_count / interval / 1e9 * 8;
41 |
42 | profile->last_10_throughput[profile->record_count % 10] = throughput;
43 | profile->record_count += 1;
44 | WV_U8 count = 10;
45 | if (count > profile->record_count) {
46 | count = profile->record_count;
47 | }
48 | WV_F throughput_avg = 0;
49 | for (WV_U8 i = 0; i < count && i < 10; i += 1) {
50 | throughput_avg += profile->last_10_throughput[i];
51 | }
52 | throughput_avg /= count;
53 |
54 | printf("checkpoint: %f ms, throughput: %f(%f) Gbps (last %d avg.)\n", current * 1000, throughput, throughput_avg, count);
55 | return 0;
56 | }
--------------------------------------------------------------------------------
/native/runtime/profile.h:
--------------------------------------------------------------------------------
1 | #ifndef WEAVER_RUNTIME_PROFILE_H
2 | #define WEAVER_RUNTIME_PROFILE_H
3 |
4 | #include "types.h"
5 |
6 | typedef struct _WV_Profile {
7 | WV_U64 interval_byte_count;
8 | WV_U32 interval_packet_count;
9 | WV_U32 next_checkpoint_sec;
10 | WV_F last_record_sec;
11 | WV_F last_10_throughput[10];
12 | WV_U8 record_count;
13 | } WV_Profile;
14 |
15 | WV_U8 WV_ProfileStart(WV_Profile *);
16 |
17 | WV_U8 WV_ProfileRecord(WV_Profile *, WV_U32, WV_U8);
18 |
19 | WV_U8 WV_ProfileRecordPrint(WV_Profile *);
20 |
21 | #endif
--------------------------------------------------------------------------------
/native/runtime/seq_next.h:
--------------------------------------------------------------------------------
1 | #ifndef WEAVER_RUNTIME_SEQ_NEXT_H
2 | #define WEAVER_RUNTIME_SEQ_NEXT_H
3 |
4 | #include "malloc.h"
5 | #include "types.h"
6 |
7 | #define WV_CONFIG_SeqNodeCount 32
8 | #define WV_CONFIG_SeqBufferSize (8 * (1 << 10))
9 |
10 | typedef struct {
11 | WV_U32 left, right;
12 | } _Part;
13 |
14 | typedef struct {
15 | WV_U32 offset;
16 | _Part parts[WV_CONFIG_SeqNodeCount];
17 | WV_U8 part_count;
18 | } ZeroBasedSeq;
19 |
20 | WV_U8 InitSeqZD(ZeroBasedSeq *seq) {
21 | seq->offset = 0;
22 | seq->part_count = 0;
23 | }
24 |
25 | #endif
--------------------------------------------------------------------------------
/native/runtime/seq_test.c:
--------------------------------------------------------------------------------
1 | #include "seq.h"
2 | #include
3 | #include
4 | #include
5 |
6 | void test_create() {
7 | WV_Seq seq;
8 | WV_InitSeq(&seq, 1, 0);
9 | WV_CleanSeq(&seq, 1);
10 | }
11 |
12 | void test_insert_in_order() {
13 | WV_Seq seq;
14 | WV_InitSeq(&seq, 1, 0);
15 | WV_Byte buf[100];
16 | for (int i = 0; i < 100; i += 1) {
17 | memset(buf, i, sizeof(buf));
18 | WV_ByteSlice payload = {.cursor = buf, .length = sizeof(buf)};
19 | WV_Insert(&seq, i * sizeof(buf), payload, sizeof(buf), 1, 0, 65536);
20 | WV_Byte *free_ptr;
21 | WV_ByteSlice assembled = WV_SeqAssemble(&seq, &free_ptr, 1);
22 | assert(assembled.length == payload.length);
23 | assert(
24 | memcmp(assembled.cursor, payload.cursor, sizeof(assembled.length)) == 0);
25 | if (free_ptr != NULL) {
26 | free(free_ptr);
27 | }
28 | }
29 | WV_CleanSeq(&seq, 1);
30 | }
31 |
32 | void test_insert_out_of_order() {
33 | WV_Seq seq;
34 | WV_InitSeq(&seq, 1, 1);
35 | WV_Byte buf[100];
36 | memset(buf, 0xCC, sizeof(buf));
37 | WV_ByteSlice payload = {.cursor = buf, .length = sizeof(buf)};
38 | WV_Insert(&seq, sizeof(buf), payload, sizeof(buf), 1, 0, 65536);
39 | WV_Byte *free_ptr;
40 | assert(WV_SeqAssemble(&seq, &free_ptr, 1).length == 0);
41 | memset(buf, 0xCD, sizeof(buf));
42 | WV_Insert(&seq, 0, payload, sizeof(buf), 1, 0, 65536);
43 | WV_ByteSlice assembled = WV_SeqAssemble(&seq, &free_ptr, 1);
44 | assert(assembled.length == 2 * sizeof(buf));
45 | for (int i = 0; i < 2 * sizeof(buf); i += 1) {
46 | assert(assembled.cursor[i] == (i < sizeof(buf) ? 0xCD : 0xCC));
47 | }
48 | if (free_ptr != NULL) {
49 | free(free_ptr);
50 | }
51 | WV_CleanSeq(&seq, 1);
52 | }
53 |
54 | void (*TESTCASES[])() = {
55 | test_create, test_insert_in_order, test_insert_out_of_order, NULL};
56 |
57 | int main() {
58 | for (int i = 0; TESTCASES[i] != NULL; i += 1) {
59 | TESTCASES[i]();
60 | }
61 | return 0;
62 | }
--------------------------------------------------------------------------------
/native/runtime/timer.h:
--------------------------------------------------------------------------------
1 | #ifndef WEAVER_NATIVE_RUNTIME_TIMER_H
2 | #define WEAVER_NATIVE_RUNTIME_TIMER_H
3 |
4 | #include "types.h"
5 | #include
6 |
7 | #define TIMEOUT 30
8 |
9 | #define TIMER_FIELDS(inst_type) \
10 | inst_type *inst_type##_timer_head, *inst_type##_timer_last;
11 |
12 | #define TIMER_INJECT_FIELDS(inst_type) \
13 | struct inst_type *prev, *next; \
14 | WV_U64 last_update;
15 |
16 | #define TIMER_INIT(rt, inst_type) \
17 | rt->inst_type##_timer_head = rt->inst_type##_timer_last = NULL
18 |
19 | #define TIMER_INSERT(rt, inst_type, inst) \
20 | if (rt->inst_type##_timer_last == NULL) { \
21 | rt->inst_type##_timer_head = rt->inst_type##_timer_last = inst; \
22 | inst->prev = inst->next = NULL; \
23 | } else { \
24 | inst->prev = NULL; \
25 | inst->next = rt->inst_type##_timer_head; \
26 | rt->inst_type##_timer_head->prev = inst; \
27 | rt->inst_type##_timer_head = inst; \
28 | } \
29 | struct timeval tv; \
30 | gettimeofday(&tv, NULL); \
31 | inst->last_update = tv.tv_sec
32 |
33 | #define TIMER_FETCH(rt, inst_type, inst) \
34 | if (inst->prev != NULL) { \
35 | inst->prev->next = inst->next; \
36 | } \
37 | if (inst->next != NULL) { \
38 | inst->next->prev = inst->prev; \
39 | } else { \
40 | rt->inst_type##_timer_last = inst->prev; \
41 | } \
42 | if (inst->prev != NULL) { \
43 | inst->prev = NULL; \
44 | inst->next = rt->inst_type##_timer_head; \
45 | rt->inst_type##_timer_head->prev = inst; \
46 | rt->inst_type##_timer_head = inst; \
47 | } \
48 | struct timeval tv; \
49 | gettimeofday(&tv, NULL); \
50 | inst->last_update = tv.tv_sec
51 |
52 | #endif
--------------------------------------------------------------------------------
/native/runtime/tommyds/.gitignore:
--------------------------------------------------------------------------------
1 | # archives
2 | *.zip
3 | *.tar.gz
4 |
5 | # backups
6 | *~
7 |
8 | # autotools
9 | # Makefile
10 | Makefile.in
11 | aclocal.m4
12 | autom4te.cache/
13 | config.guess
14 | config.h
15 | config.h.in
16 | config.log
17 | config.status
18 | config.sub
19 | configure
20 | install-sh
21 | missing
22 | stamp-h1
23 |
24 | # objects
25 | *.o
26 | *.s
27 | *.S
28 |
29 | # coverage
30 | *.gcda
31 | *.gcno
32 | *.info
33 | cov/
34 |
35 | # project
36 | *.dst
37 | *.epr
38 | makebench.sh
39 |
40 | # specific
41 | tommycheck
42 | tommybench
43 | contrib/
44 | archive/
45 | *.ttf
46 | doc/
47 | benchmark/data/
48 | benchmark/exec/
49 | www/
50 |
51 |
52 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/.travis.yml:
--------------------------------------------------------------------------------
1 | # Travis CI configuration file
2 |
3 | sudo: false
4 |
5 | language: c
6 |
7 | script: make check
8 |
9 | compiler:
10 | - clang
11 | - gcc
12 |
13 | os:
14 | - linux
15 | - osx
16 |
17 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/AUTHORS:
--------------------------------------------------------------------------------
1 | TommyDS AUTHORS
2 | ===============
3 |
4 | The author of TommyDS is Andrea Mazzoleni.
5 |
6 | You can contact me sending an email at:
7 |
8 | amadvance@gmail.com
9 |
10 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/HISTORY:
--------------------------------------------------------------------------------
1 | TommyDS HISTORY
2 | ===============
3 |
4 | 3.0 2018/04
5 | ===========
6 | * Use 64 bits integers when building on a 64 bits platforms. You can store
7 | more than 2^32 objects in the containers. This doesn't applies to tries
8 | that are able to store only 32 bit integers, but you can change this with
9 | the TOMMY_TRIE_BIT and TOMMY_TRIE_INPLACE_BIT definitions.
10 | * Removed the tommy_count_t type that is now always replaced by tommy_size_t.
11 | * Renamed the "key" field of the tommy_node_t to "index" to be more generic
12 | on the possible use.
13 |
14 | 2.2 2018/02
15 | ===========
16 | * Removed tommy_list_remove_head_not_empty() as not used and wrongly
17 | implemented [Daniel Roethlisberger].
18 |
19 | 2.1 2016/11
20 | ===========
21 | * Added a new hash function for strings: tommy_strhash_u32().
22 | * Added a new tree implementation. It's not intended to be fast but useful if
23 | you need elements in order.
24 | * Fixed some references to TOMMY_ARRAYBLKOF_SIZE, where instead
25 | TOMMY_ARRAYBLK_SIZE was incorrectly used [Rocco].
26 |
27 | 2.0 2014/12
28 | ===========
29 | * Fixed a Segmentation Fault bug in the trie_inplace container when inserting
30 | duplicate elements.
31 | * Faster array and hashlin implementation when accessing elements.
32 | * Added new hashtable functions to iterate over all the elements.
33 | * Added a new tommy_calloc() function used for allocating initialized memory.
34 | If you redefined tommy_malloc(), likely you have to redefine also tommy_calloc().
35 | * Reached 100% code coverage in the regression test.
36 | * Different source code organization.
37 | * Added benchmark comparison with Binary Search Tesseract by Gregorius van
38 | den Hoven.
39 |
40 | 1.8 2013/12
41 | ===========
42 | * Fixed build of tommy_arrayblk in C++.
43 | * Changed the default node size of tommy_trie to fit a cache line of 64 bytes.
44 | * Added benchmark comparison with STX BTree.
45 |
46 | 1.7 2013/12
47 | ===========
48 | * Extends tommy_hashlin_done() to work also if the hashtable is not empty.
49 | * Removes the empty tommy_trie_done() because the real deallocation is done
50 | by the allocator.
51 |
52 | 1.6 2013/11
53 | ===========
54 | * Added a new tommy_arrayblk and tommy_arrayblkof types to store elements
55 | in an array minimizing memory occupation.
56 |
57 | 1.5 2013/06
58 | ===========
59 | * Fixed inline declaration to allow building with clang.
60 | * Added a new tommy_arrayof type to store in an array elements of arbitrary
61 | size.
62 |
63 | 1.4 2013/03
64 | ===========
65 | * Added benchmark comparison with Google BTree, and C++ map and unordered_map.
66 | * Benchmark for Linux is now compiled with "-O3 -march=pentium4 -mtune=generic",
67 | and the Windows one with "/Ox /GL /GS- /arch:SSE2".
68 |
69 | 1.3 2013/02
70 | ===========
71 | * Fixed a Segmentation Fault bug in the hashlin container if exact power
72 | of 2 sizes were used.
73 | * Removed some warnings with newer gcc.
74 | * Minor documentation changes.
75 | * Added benchmark comparison with the judy array implementation by Karl Malbrain.
76 |
77 | 1.2 2012/05
78 | ===========
79 | * Minor documentation changes.
80 | * In the check application, added a speed comparison with the C qsort()
81 | implementation.
82 |
83 | 1.1 2012/05
84 | ===========
85 | * Fixed the tommy_hashdyn_remove() function. Now it shrinks the hashtable if required.
86 | * Minor documentation changes.
87 |
88 | 1.0 2011/03
89 | ===========
90 | * First official version of TommyDS.
91 | * Added tommy_list_foreach functions.
92 |
93 | 0.2 2011/03
94 | ===========
95 | * Added tommy_array. A dynamic vector.
96 |
97 | 0.1 2011/01
98 | ===========
99 | * First release of Tommy.
100 |
101 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/INSTALL:
--------------------------------------------------------------------------------
1 | TommyDS INSTALL
2 | ===============
3 |
4 | TommyDS doesn't need any installation.
5 |
6 | You have only to import the required .c and .h files into your program
7 | and use the them.
8 |
9 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010, Andrea Mazzoleni. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions
5 | are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 |
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/Makefile:
--------------------------------------------------------------------------------
1 | #############################################################################
2 | # Tommy Makefile
3 |
4 | # Version of TommyDS
5 | VERSION = 3.0
6 |
7 | # Build options for the check program
8 | ifdef COVERAGE
9 | CFLAGS = -O0 -g -fprofile-arcs -ftest-coverage
10 | else
11 | CFLAGS = -O3 -march=native -Wall -Wextra -Wshadow -Wuninitialized -Wcast-align -Wcast-qual -g
12 | endif
13 |
14 | # Build options for the benchmark
15 | # -std=gnu++0x required by Google btree
16 | BENCHCXXFLAGS = -m32 -O3 -march=native -flto -fpermissive -std=gnu++0x -Wall -g
17 |
18 | # Programs
19 | CC ?= gcc
20 | CXX ?= g++
21 | OBJDUMP ?= objdump
22 | UNAME = $(shell uname)
23 |
24 | # Linux
25 | ifeq ($(UNAME),Linux)
26 | LIB=-lrt
27 | BENCHLIB=benchmark/lib/judy/libJudyL.a benchmark/lib/judy/libJudyMalloc.a
28 | EXE=
29 | OX=.o
30 | endif
31 |
32 | # Darwin
33 | ifeq ($(UNAME),Darwin)
34 | LIB=
35 | EXE=
36 | OX=.o
37 | endif
38 |
39 | # Windows
40 | ifeq ($(UNAME),)
41 | BENCHLIB=benchmark/lib/judy/src/judy.lib
42 | EXE=.exe
43 | OX=.obj
44 | endif
45 |
46 | #CHECK = ./tommybench -n 1000000 -d tommy-hashlin
47 | CHECK = ./tommycheck
48 |
49 | DEP = \
50 | tommyds/tommyalloc.c \
51 | tommyds/tommyalloc.h \
52 | tommyds/tommyarray.c \
53 | tommyds/tommyarray.h \
54 | tommyds/tommyarrayof.c \
55 | tommyds/tommyarrayof.h \
56 | tommyds/tommyarrayblk.c \
57 | tommyds/tommyarrayblk.h \
58 | tommyds/tommyarrayblkof.c \
59 | tommyds/tommyarrayblkof.h \
60 | tommyds/tommy.c \
61 | tommyds/tommy.h \
62 | tommyds/tommyhash.c \
63 | tommyds/tommyhashdyn.c \
64 | tommyds/tommyhashdyn.h \
65 | tommyds/tommyhash.h \
66 | tommyds/tommyhashlin.c \
67 | tommyds/tommyhashlin.h \
68 | tommyds/tommyhashtbl.c \
69 | tommyds/tommyhashtbl.h \
70 | tommyds/tommylist.c \
71 | tommyds/tommylist.h \
72 | tommyds/tommytrie.c \
73 | tommyds/tommytrie.h \
74 | tommyds/tommytrieinp.c \
75 | tommyds/tommytrieinp.h \
76 | tommyds/tommytypes.h \
77 | tommyds/tommychain.h
78 |
79 | DEPTEST = \
80 | check.c \
81 | benchmark.cc
82 |
83 | all: tommycheck$(EXE)
84 |
85 | bench: tommybench$(EXE)
86 |
87 | tommy$(OX): $(DEP)
88 | $(CC) $(CFLAGS) -c tommyds/tommy.c -o tommy$(OX)
89 | -$(OBJDUMP) -S tommy$(OX) > tommy.s
90 |
91 | tommycheck$(EXE): check.c tommy$(OX)
92 | $(CC) $(CFLAGS) check.c tommy$(OX) -o tommycheck$(EXE) $(LIB)
93 |
94 | tommybench$(EXE): benchmark.cc $(DEP)
95 | $(CXX) $(BENCHCXXFLAGS) benchmark.cc -o tommybench$(EXE) $(LIB) $(BENCHLIB)
96 |
97 | check: tommycheck$(EXE)
98 | ./tommycheck$(EXE)
99 | echo Check completed with success!
100 |
101 | lcov_reset:
102 | lcov -d . -z
103 | rm -f ./lcov.info
104 |
105 | lcov_capture:
106 | lcov -d . --capture -o lcov.info
107 |
108 | lcov_html:
109 | rm -rf ./cov
110 | mkdir cov
111 | genhtml -o ./cov lcov.info
112 |
113 | coverage:
114 | $(MAKE) COVERAGE=1 tommycheck$(EXE)
115 | $(MAKE) lcov_reset
116 | ./tommycheck$(EXE)
117 | $(MAKE) lcov_capture
118 | $(MAKE) lcov_html
119 |
120 | valgrind:
121 | valgrind \
122 | --tool=memcheck \
123 | --track-origins=yes \
124 | --read-var-info=yes \
125 | -v $(CHECK) \
126 | 2> valgrind.log
127 | tail valgrind.log
128 |
129 | callgrind:
130 | valgrind \
131 | --tool=callgrind \
132 | --dump-instr=yes \
133 | --trace-jump=yes \
134 | -v $(CHECK) \
135 | 2> callgrind.log
136 | tail callgrind.log
137 |
138 | cachegrind:
139 | valgrind \
140 | --tool=cachegrind \
141 | -v $(CHECK) \
142 | 2> cachegrind.log
143 | tail cachegrind.log
144 |
145 | phony:
146 |
147 | graph: phony
148 | cd benchmark && sh gr_all.sh
149 |
150 | doc: phony tommy.doxygen tommy.css $(DEP)
151 | rm -rf doc
152 | mkdir doc
153 | cp -a benchmark/data/def doc/def
154 | cp -a benchmark/data/other doc/other
155 | cp -a benchmark/data/core_i5_650_3G2_linux doc/core_i5_650_3G2_linux
156 | rm -f doc/*/*.lst
157 | rm -f doc/*/*.gnu
158 | doxygen tommy.doxygen
159 | rm -f doc/doxygen.png
160 | rm -f doc/tab_*.png
161 |
162 | web: phony tommyweb.doxygen tommy.css $(DEP)
163 | rm -rf web
164 | mkdir web
165 | cp -a benchmark/data/def web/def
166 | cp -a benchmark/data/other web/other
167 | cp -a benchmark/data/core_i5_650_3G2_linux web/core_i5_650_3G2_linux
168 | rm -f web/*/*.lst
169 | rm -f web/*/*.gnu
170 | doxygen tommyweb.doxygen
171 | rm -f web/doxygen.png
172 | rm -f web/tab_*.png
173 |
174 | clean:
175 | rm -f *.log *.s *.lst *.o
176 | rm -f *.ncb *.suo *.obj
177 | rm -f *.gcno *.gcda lcov.info
178 | rm -rf Debug Release x64
179 | rm -f callgrind.out.*
180 | rm -f cachegrind.out.*
181 |
182 | distclean: clean
183 | rm -f tommybench$(EXE) tommycheck$(EXE)
184 |
185 | maintainerclean: distclean
186 | rm -rf doc web
187 |
188 | DIST=tommyds-$(VERSION)
189 |
190 | DISTFILES=\
191 | Makefile \
192 | README LICENSE AUTHORS INSTALL HISTORY \
193 | tommy.doxygen tommy.css tommy-header.html tommy-footer.html \
194 | benchmark.vcxproj benchmark.sln \
195 | benchmark.geany \
196 | benchmark.cc \
197 | check.c
198 |
199 | dist:
200 | mkdir $(DIST)
201 | mkdir $(DIST)/tommyds
202 | cp $(DISTFILES) $(DIST)
203 | cp $(DEP) $(DIST)/tommyds
204 | cp $(DEPTEST) $(DIST)
205 | cp -R doc $(DIST)
206 | cp -R benchmark $(DIST)/benchmark
207 | rm -f $(DIST)/benchmark/data/*/*.png
208 | rm -rf $(DIST)/benchmark/data/test
209 | rm -f $(DIST)/benchmark/arial.ttf
210 | rm -f $(DIST).tar.gz
211 | tar cfzo $(DIST).tar.gz $(DIST)
212 | rm -f $(DIST).zip
213 | zip -r $(DIST).zip $(DIST)
214 | rm -r $(DIST)
215 |
216 | distcheck: dist
217 | tar zxvf $(DIST).tar.gz
218 | cd $(DIST) && make check
219 | rm -rf $(DIST)
220 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/README:
--------------------------------------------------------------------------------
1 | TommyDS
2 | =======
3 |
4 | TommyDS is a C library of array, hashtables and tries data structures,
5 | designed for high performance and providing an easy to use interface.
6 |
7 | It's faster than all the similar libraries like rbtree, judy, goodledensehash,
8 | khash, uthash, nedtries and others.
9 |
10 | The data structures provided are:
11 |
12 | tommy_list - A double linked list.
13 | tommy_array - A linear array. It doesn't fragment
14 | the heap.
15 | tommy_arrayblk - A blocked linear array. It doesn't fragment
16 | the heap and it minimizes the space occupation.
17 | tommy_hashtable - A fixed size chained hashtable.
18 | tommy_hashdyn - A dynamic chained hashtable.
19 | tommy_hashlin - A linear chained hashtable. It doesn't have the
20 | problem of the delay when resizing and it doesn't
21 | fragment the heap.
22 | tommy_trie - A trie optimized for cache utilization.
23 | tommy_trie_inplace - A trie completely inplace.
24 |
25 | The documentation is available in HTML format in the doc/index.html file,
26 | and directly in the .h files.
27 |
28 | The official site of TommyDS is:
29 |
30 | http://www.tommyds.it
31 |
32 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark.geany:
--------------------------------------------------------------------------------
1 |
2 | [indentation]
3 | indent_width=4
4 | indent_type=1
5 | indent_hard_tab_width=8
6 | detect_indent=false
7 | indent_mode=2
8 |
9 | [project]
10 | name=benchmark
11 | base_path=/home/am/Desktop/tommy/
12 | make_in_base_path=true
13 | description=
14 | run_cmd=./tommy
15 |
16 | [files]
17 | current_page=1
18 | FILE_NAME_0=940;Make;0;16;1;1;0;/home/am/Desktop/tommy/Makefile;0
19 | FILE_NAME_1=4126;C;0;16;1;1;0;/home/am/Desktop/tommy//tommyhash.c;0
20 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 11.00
3 | # Visual Studio 2010
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "benchmark", "benchmark.vcxproj", "{E77E7CFB-E02E-4F25-ADAA-1CF587DB0A04}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Debug|x64 = Debug|x64
10 | Release|Win32 = Release|Win32
11 | Release|x64 = Release|x64
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {E77E7CFB-E02E-4F25-ADAA-1CF587DB0A04}.Debug|Win32.ActiveCfg = Debug|Win32
15 | {E77E7CFB-E02E-4F25-ADAA-1CF587DB0A04}.Debug|Win32.Build.0 = Debug|Win32
16 | {E77E7CFB-E02E-4F25-ADAA-1CF587DB0A04}.Debug|x64.ActiveCfg = Debug|x64
17 | {E77E7CFB-E02E-4F25-ADAA-1CF587DB0A04}.Debug|x64.Build.0 = Debug|x64
18 | {E77E7CFB-E02E-4F25-ADAA-1CF587DB0A04}.Release|Win32.ActiveCfg = Release|Win32
19 | {E77E7CFB-E02E-4F25-ADAA-1CF587DB0A04}.Release|Win32.Build.0 = Release|Win32
20 | {E77E7CFB-E02E-4F25-ADAA-1CF587DB0A04}.Release|x64.ActiveCfg = Release|x64
21 | {E77E7CFB-E02E-4F25-ADAA-1CF587DB0A04}.Release|x64.Build.0 = Release|x64
22 | EndGlobalSection
23 | GlobalSection(SolutionProperties) = preSolution
24 | HideSolutionNode = FALSE
25 | EndGlobalSection
26 | EndGlobal
27 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_all.bat:
--------------------------------------------------------------------------------
1 | rem Set it to a GNUPLOT 4.4 binary
2 | rem In case download it from http://sourceforge.net/projects/gnuplot/files/gnuplot/4.4.2/gp442win32.zip/download
3 | set GNUPLOT=..\contrib\gnuplot\binary\gnuplot.exe
4 |
5 | %GNUPLOT% gr_def_random_hit.gnu
6 | %GNUPLOT% gr_def_random_change.gnu
7 | %GNUPLOT% gr_other_judy_problem.gnu
8 | %GNUPLOT% gr_other_slow_problem.gnu
9 |
10 | DIR=data\core_i5_650_3G2_linux
11 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_insert.gnu
12 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_hit.gnu
13 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_insert.gnu
14 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_miss.gnu
15 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_change.gnu
16 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_remove.gnu
17 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_size.gnu
18 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_hit.gnu
19 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_insert.gnu
20 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_miss.gnu
21 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_change.gnu
22 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_remove.gnu
23 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_size.gnu
24 |
25 | DIR=data\core_i7_3740_2G7_win
26 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_insert.gnu
27 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_hit.gnu
28 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_insert.gnu
29 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_miss.gnu
30 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_change.gnu
31 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_remove.gnu
32 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_size.gnu
33 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_hit.gnu
34 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_insert.gnu
35 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_miss.gnu
36 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_change.gnu
37 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_remove.gnu
38 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_size.gnu
39 |
40 | DIR=data\test
41 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_insert.gnu
42 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_hit.gnu
43 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_insert.gnu
44 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_miss.gnu
45 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_change.gnu
46 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_remove.gnu
47 | %GNUPLOT% %DIR%\gr_def.gnu gr_forward_size.gnu
48 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_hit.gnu
49 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_insert.gnu
50 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_miss.gnu
51 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_change.gnu
52 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_remove.gnu
53 | %GNUPLOT% %DIR%\gr_def.gnu gr_random_size.gnu
54 |
55 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_all.sh:
--------------------------------------------------------------------------------
1 | echo Ensure to use GNUPLOT 4.4
2 |
3 | export GDFONTPATH=.
4 | export GNUPLOT_DEFAULT_GDFONT=arial
5 |
6 | gnuplot gr_def_random_hit.gnu
7 | gnuplot gr_def_random_change.gnu
8 | gnuplot gr_other_judy_problem.gnu
9 | gnuplot gr_other_googlelibchash_problem.gnu
10 | gnuplot gr_other_ck_problem.gnu
11 |
12 | DIR=data/core_i5_650_3G2_linux
13 | gnuplot $DIR/gr_def.gnu gr_forward_insert.gnu
14 | gnuplot $DIR/gr_def.gnu gr_forward_hit.gnu
15 | gnuplot $DIR/gr_def.gnu gr_forward_insert.gnu
16 | gnuplot $DIR/gr_def.gnu gr_forward_miss.gnu
17 | gnuplot $DIR/gr_def.gnu gr_forward_change.gnu
18 | gnuplot $DIR/gr_def.gnu gr_forward_remove.gnu
19 | gnuplot $DIR/gr_def.gnu gr_forward_size.gnu
20 | gnuplot $DIR/gr_def.gnu gr_random_hit.gnu
21 | gnuplot $DIR/gr_def.gnu gr_random_insert.gnu
22 | gnuplot $DIR/gr_def.gnu gr_random_miss.gnu
23 | gnuplot $DIR/gr_def.gnu gr_random_change.gnu
24 | gnuplot $DIR/gr_def.gnu gr_random_remove.gnu
25 | gnuplot $DIR/gr_def.gnu gr_random_size.gnu
26 |
27 | DIR=data/core_i7_3740_2G7_linux
28 | gnuplot $DIR/gr_def.gnu gr_forward_insert.gnu
29 | gnuplot $DIR/gr_def.gnu gr_forward_hit.gnu
30 | gnuplot $DIR/gr_def.gnu gr_forward_insert.gnu
31 | gnuplot $DIR/gr_def.gnu gr_forward_miss.gnu
32 | gnuplot $DIR/gr_def.gnu gr_forward_change.gnu
33 | gnuplot $DIR/gr_def.gnu gr_forward_remove.gnu
34 | gnuplot $DIR/gr_def.gnu gr_forward_size.gnu
35 | gnuplot $DIR/gr_def.gnu gr_random_hit.gnu
36 | gnuplot $DIR/gr_def.gnu gr_random_insert.gnu
37 | gnuplot $DIR/gr_def.gnu gr_random_miss.gnu
38 | gnuplot $DIR/gr_def.gnu gr_random_change.gnu
39 | gnuplot $DIR/gr_def.gnu gr_random_remove.gnu
40 | gnuplot $DIR/gr_def.gnu gr_random_size.gnu
41 |
42 | DIR=data/core_i7_3740_2G7_win
43 | gnuplot $DIR/gr_def.gnu gr_forward_insert.gnu
44 | gnuplot $DIR/gr_def.gnu gr_forward_hit.gnu
45 | gnuplot $DIR/gr_def.gnu gr_forward_insert.gnu
46 | gnuplot $DIR/gr_def.gnu gr_forward_miss.gnu
47 | gnuplot $DIR/gr_def.gnu gr_forward_change.gnu
48 | gnuplot $DIR/gr_def.gnu gr_forward_remove.gnu
49 | gnuplot $DIR/gr_def.gnu gr_forward_size.gnu
50 | gnuplot $DIR/gr_def.gnu gr_random_hit.gnu
51 | gnuplot $DIR/gr_def.gnu gr_random_insert.gnu
52 | gnuplot $DIR/gr_def.gnu gr_random_miss.gnu
53 | gnuplot $DIR/gr_def.gnu gr_random_change.gnu
54 | gnuplot $DIR/gr_def.gnu gr_random_remove.gnu
55 | gnuplot $DIR/gr_def.gnu gr_random_size.gnu
56 |
57 | DIR=data/test
58 | gnuplot $DIR/gr_def.gnu gr_forward_insert.gnu
59 | gnuplot $DIR/gr_def.gnu gr_forward_hit.gnu
60 | gnuplot $DIR/gr_def.gnu gr_forward_insert.gnu
61 | gnuplot $DIR/gr_def.gnu gr_forward_miss.gnu
62 | gnuplot $DIR/gr_def.gnu gr_forward_change.gnu
63 | gnuplot $DIR/gr_def.gnu gr_forward_remove.gnu
64 | gnuplot $DIR/gr_def.gnu gr_forward_size.gnu
65 | gnuplot $DIR/gr_def.gnu gr_random_hit.gnu
66 | gnuplot $DIR/gr_def.gnu gr_random_insert.gnu
67 | gnuplot $DIR/gr_def.gnu gr_random_miss.gnu
68 | gnuplot $DIR/gr_def.gnu gr_random_change.gnu
69 | gnuplot $DIR/gr_def.gnu gr_random_remove.gnu
70 | gnuplot $DIR/gr_def.gnu gr_random_size.gnu
71 |
72 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_common.gnu:
--------------------------------------------------------------------------------
1 | ;set term svg enhanced font 'arial,10' size 800,800
2 | ;bext = ".svg"
3 | set terminal png nocrop enhanced font arial 10 size 800,800
4 | bext = ".png"
5 | set xtics nomirror rotate by -45 font "arial,8"
6 | set key below
7 | set style data linespoints
8 | set datafile missing "0"
9 | set xlabel "Number of elements in logarithmic scale"
10 | set ylabel "Time for element in nanosecond in logarithmic scale\nLower is better"
11 | set xrange [1000:10000000]
12 | set yrange [6:1000]
13 | set logscale y
14 | set logscale x
15 | set format y "%.0fns"
16 | set format x "%.0s%c"
17 | bdir = "data/"
18 |
19 | # for some colors see: http://www.uni-hamburg.de/Wiss/FB/15/Sustainability/schneider/gnuplot/colors.htm
20 | set style line 1 lc 1 lt 1 # hashtable
21 | set style line 2 lc 2 lt 2 # hashdyn
22 | set style line 3 lc 3 lt 3 # hashlin
23 | set style line 4 lc 4 lt 4 # trie
24 | set style line 5 lc 5 lt 5 # trie-inplace
25 | set style line 6 lc 6 lt 6 # rbtre
26 | set style line 7 lc 7 lt 7 # nedtrie
27 | set style line 8 lc 8 lt 8 # khash
28 | set style line 9 lc 9 lt 8 # uthash
29 | set style line 10 lc 10 lt 10 # judy
30 | set style line 11 lc 11 lt 11 # judyarray
31 | set style line 12 lc 12 lt 12 # googledensehash
32 | set style line 13 lc rgb "#FF69B4" lt 13 # googlebtree
33 | set style line 14 lc 14 lt 14 # stxbtree
34 | set style line 15 lc 15 lt 15 # c++unorderedmap
35 | set style line 16 lc 16 lt 16 # c++map
36 | set style line 17 lc 17 lt 17 # tesseract
37 | set style line 18 lc 4 lt 18 pt 1 # libdynamic
38 | set style line 19 lc rgb "#FF69B4" lt 19 # googlelibchash
39 | set style line 20 lc rgb "#1E90FF" lt 20 # concurrencykit
40 |
41 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_def_random_change.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | tdir = "def/"
4 | tsub = "\nCore i5 650 3.20 GHz, 4 MB L3 cache, 2400 Uncore Speed\nLinux, gcc 6.2.0, 32 bit"
5 |
6 | set output bdir.tdir."img_random_change".bext
7 | set title "Random Change (Remove + Insert)".tsub
8 | data = bdir.tdir.'dat_random_change.lst'
9 |
10 | plot data using 1:2 title columnheader(2), \
11 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
12 |
13 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_def_random_hit.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | tdir = "def/"
4 | tsub = "\nCore i5 650 3.20 GHz, 4 MB L3 cache, 2400 Uncore Speed\nLinux, gcc 6.2.0, 32 bit"
5 |
6 | set output bdir.tdir."img_random_hit".bext
7 | set title "Random Hit".tsub
8 | data = bdir.tdir.'dat_random_hit.lst'
9 |
10 | plot data using 1:2 title columnheader(2), \
11 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
12 |
13 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_forward_change.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_forward_change".bext
4 | set title "Forward Change (Remove + Insert)".tsub
5 | data = bdir.tdir.'dat_forward_change.lst'
6 |
7 | plot data using 1:2 title columnheader(2), \
8 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
9 |
10 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_forward_hit.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_forward_hit".bext
4 | set title "Forward Hit".tsub
5 | data = bdir.tdir.'dat_forward_hit.lst'
6 |
7 | plot data using 1:2 title columnheader(2), \
8 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
9 |
10 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_forward_insert.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_forward_insert".bext
4 | set title "Forward Insert".tsub
5 | data = bdir.tdir.'dat_forward_insert.lst'
6 |
7 | plot data using 1:2 title columnheader(2), \
8 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
9 |
10 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_forward_miss.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_forward_miss".bext
4 | set title "Forward Miss".tsub
5 | data = bdir.tdir.'dat_forward_miss.lst'
6 |
7 | plot data using 1:2 title columnheader(2), \
8 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
9 |
10 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_forward_remove.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_forward_remove".bext
4 | set title "Forward Remove".tsub
5 | data = bdir.tdir.'dat_forward_remove.lst'
6 |
7 | plot data using 1:2 title columnheader(2), \
8 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
9 |
10 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_forward_size.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_forward_size".bext
4 | set title "Size".tsub
5 | set format y "%.0f"
6 | set ylabel "Size for element in byte\nLower is better"
7 | unset logscale y
8 | set yrange [0:80]
9 | data = bdir.tdir.'dat_forward_size.lst'
10 |
11 | plot data using 1:2 title columnheader(2), \
12 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
13 |
14 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_other_ck_problem.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set yrange [10:10000]
4 |
5 | tdir = "other/"
6 | tsub = "\nCore i5 650 3.20 GHz, 4 MB L3 cache\nLinux, gcc 4.7.1, 32 bit"
7 |
8 | set output bdir.tdir."ck_problem".bext
9 | set title "Random Change (Remove + Insert)".tsub
10 | data = bdir.tdir.'ck_problem.lst'
11 |
12 | plot data using 1:2 title columnheader(2), \
13 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
14 |
15 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_other_googlelibchash_problem.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set yrange [10:10000]
4 |
5 | tdir = "other/"
6 | tsub = "\nCore i5 650 3.20 GHz, 4 MB L3 cache\nLinux, gcc 4.7.1, 32 bit"
7 |
8 | set output bdir.tdir."googlelibchash_problem".bext
9 | set title "Random Change (Remove + Insert)".tsub
10 | data = bdir.tdir.'googlelibchash_problem.lst'
11 |
12 | plot data using 1:2 title columnheader(2), \
13 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
14 |
15 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_other_judy_problem.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set yrange [10:10000]
4 |
5 | tdir = "other/"
6 | tsub = "\nXeon E5430 2.66 GHz, 2x6 MB L2 cache, 1333 MT/s FSB\nWindows, Visual C 2008, 32 bit"
7 |
8 | set output bdir.tdir."judy_problem".bext
9 | set title "Forward Change (Remove + Insert)".tsub
10 | data = bdir.tdir.'judy_problem.lst'
11 |
12 | plot data using 1:2 title columnheader(2), \
13 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
14 |
15 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_random_change.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_random_change".bext
4 | set title "Random Change (Remove + Insert)".tsub
5 | data = bdir.tdir.'dat_random_change.lst'
6 |
7 | plot data using 1:2 title columnheader(2), \
8 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
9 |
10 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_random_hit.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_random_hit".bext
4 | set title "Random Hit".tsub
5 | data = bdir.tdir.'dat_random_hit.lst'
6 |
7 | plot data using 1:2 title columnheader(2), \
8 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
9 |
10 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_random_insert.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_random_insert".bext
4 | set title "Random Insert".tsub
5 | data = bdir.tdir.'dat_random_insert.lst'
6 |
7 | plot data using 1:2 title columnheader(2), \
8 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
9 |
10 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_random_miss.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_random_miss".bext
4 | set title "Random Miss".tsub
5 | data = bdir.tdir.'dat_random_miss.lst'
6 |
7 | plot data using 1:2 title columnheader(2), \
8 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
9 |
10 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_random_remove.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_random_remove".bext
4 | set title "Random Remove".tsub
5 | data = bdir.tdir.'dat_random_remove.lst'
6 |
7 | plot data using 1:2 title columnheader(2), \
8 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
9 |
10 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/benchmark/gr_random_size.gnu:
--------------------------------------------------------------------------------
1 | load "gr_common.gnu"
2 |
3 | set output bdir.tdir."img_random_size".bext
4 | set title "Size".tsub
5 | set format y "%.0f"
6 | set ylabel "Size for element in byte\nLower is better"
7 | unset logscale y
8 | set yrange [0:80]
9 | data = bdir.tdir.'dat_random_size.lst'
10 |
11 | plot data using 1:2 title columnheader(2), \
12 | for [i=3:21] '' using 1:i title columnheader(i) ls i-1
13 |
14 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/makecov.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # Run the Coverage test
4 | #
5 |
6 | make distclean
7 |
8 | if ! make CC=gcc COVERAGE=1 lcov_reset check lcov_capture lcov_html; then
9 | exit 1
10 | fi
11 |
12 |
13 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/makescan.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 |
4 | rm -r cov-int
5 | rm tommyds.tgz
6 |
7 | make distclean
8 |
9 | export PATH=$PATH:../snapraid/contrib/cov-analysis-linux64-2017.07/bin
10 |
11 | if ! cov-build --dir cov-int make; then
12 | exit 1
13 | fi
14 |
15 | tar czf tommyds.tgz cov-int
16 |
17 | rm -r cov-int
18 |
19 | echo tommyds.tgz ready to upload to https://scan.coverity.com/projects/3780/builds/new
20 |
21 |
--------------------------------------------------------------------------------
/native/runtime/tommyds/tommy-footer.html:
--------------------------------------------------------------------------------
1 |