Skip to content

Commit bcee9c7

Browse files
author
Kai Mast
authored
Support for native and wasm binaries (#104)
This adds a standalone WebAssembly runner, as well as, the possibility to run any binary inside an OpenLambda container.
1 parent a2abbcd commit bcee9c7

94 files changed

Lines changed: 7597 additions & 3228 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,19 @@ jobs:
2929
override: true
3030
components: cargo, rustc, clippy
3131
target: wasm32-unknown-unknown
32+
- name: Install cross
33+
run: cargo install cross
34+
- name: Build open lambda
35+
run: sudo make ol wasm-worker wasm-programs native-programs install-python-bindings
36+
- name: Test Python (Docker)
37+
run: sudo ./script/test.py --worker_type=docker
38+
- name: Test Python (SOCK)
39+
run: sudo ./script/test.py --worker_type=sock
40+
- name: Test Binaries (WebAssembly)
41+
run: sudo ./script/bin-test.py --worker_type=wasm
42+
- name: Test Binaries (SOCK)
43+
run: sudo ./script/bin-test.py --worker_type=socka
44+
- name: Test SOCK
45+
run: sudo ./script/sock-test.py
46+
- name: Linting
47+
run: make lint

.gitignore

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737

3838
*~
3939
*.swp
40+
*.swo
41+
*.swn
4042

4143
.vagrant
4244
.sock
@@ -55,4 +57,27 @@
5557
/test-dir
5658
/test.json
5759

58-
ol
60+
# binaries
61+
ol
62+
ol-wasm
63+
ol-container-proxy
64+
65+
*.bin
66+
67+
bench-dir
68+
69+
test-registry.wasm/
70+
bin-functions/target/
71+
wasm-worker/target/
72+
container-proxy/target
73+
74+
lambda/runtimes/rust/target
75+
76+
bench-results.csv
77+
bench-results.pdf
78+
79+
scripts/build
80+
scripts/dist
81+
scripts/open_lambda.egg-info
82+
83+
*.lsm

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "programs"]
2+
path = programs
3+
url = ssh://[email protected]/kaimast/open-lambda-wasm-programs.git

Makefile

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,101 @@
1-
PWD = $(shell pwd)
1+
PWD=$(shell pwd)
2+
WASM_TARGET=wasm32-unknown-unknown
3+
CARGO=cargo +nightly
4+
GO=go
5+
OL_DIR=$(abspath ./src)
6+
OL_GO_FILES=$(shell find src/ -name '*.go')
7+
LAMBDA_FILES = lambda/Dockerfile lambda/Makefile lambda/spin.c lambda/runtimes/python/server.py lambda/runtimes/python/setup.py lambda/runtimes/python/ol.c
8+
USE_LLVM?=1
9+
BUILDTYPE?=debug
210

3-
GO = go
4-
OL_DIR = $(abspath ./src)
5-
OL_GO_FILES = $(shell find src/ -name '*.go')
6-
LAMBDA_FILES = lambda/Dockerfile lambda/Makefile lambda/server.py lambda/setup.py lambda/sock2.py lambda/spin.c lambda/ol.c
11+
ifeq (${USE_LLVM}, 1)
12+
WASM_WORKER_FLAGS=--features=llvm-backend
13+
else
14+
WASM_WORKER_FLAGS=
15+
endif
16+
17+
ifeq (${BUILDTYPE}, release)
18+
BUILD_FLAGS=--release
19+
else
20+
BUILD_FLAGS=
21+
endif
722

8-
.PHONY: all
923
.PHONY: install
1024
.PHONY: test-all
1125
.PHONY: clean
26+
.PHONY: update-dependencies
27+
.PHONY: wasm-functions
28+
.PHONY: wasm-worker
29+
.PHONY: native-functions
30+
.PHONY: test-dir
31+
.PHONY: check-runtime
32+
.PHONY: container-proxy
33+
.PHONY: fmt check-fmt
34+
35+
all: ol imgs/lambda wasm-worker wasm-functions native-functions
36+
37+
wasm-worker:
38+
cd wasm-worker && ${CARGO} build ${BUILD_FLAGS} ${WASM_WORKER_FLAGS}
39+
cp wasm-worker/target/${BUILDTYPE}/wasm-worker ./ol-wasm
1240

13-
all: ol imgs/lambda
41+
wasm-functions:
42+
cd bin-functions && make wasm-functions
43+
bash ./bin-functions/install-wasm.sh test-registry.wasm ${WASM_TARGET}
44+
45+
native-functions: imgs/lambda
46+
cd bin-functions && cross build --release
47+
bash ./bin-functions/install-native.sh test-registry
48+
49+
update-dependencies:
50+
cd lambda/runtimes/rust && ${CARGO} update
51+
cd wasm-worker && ${CARGO} update
52+
cd bin-functions && ${CARGO} update
53+
cd container-proxy && ${CARGO} update
1454

1555
imgs/lambda: $(LAMBDA_FILES)
1656
${MAKE} -C lambda
1757
sudo docker build -t lambda lambda
1858
touch imgs/lambda
1959

60+
install-python-bindings:
61+
cd scripts && python setup.py install
62+
63+
check-runtime:
64+
cd lambda/runtimes/rust && ${CARGO} check
65+
66+
container-proxy:
67+
cd container-proxy && ${CARGO} build ${BUILD_FLAGS}
68+
cp ./container-proxy/target/${BUILDTYPE}/open-lambda-container-proxy ./ol-container-proxy
69+
70+
test-dir:
71+
cp lambda/runtimes/rust/target/release/open-lambda-runtime ./test-registry/hello-rust.bin
72+
2073
ol: $(OL_GO_FILES)
21-
cd $(OL_DIR) && $(GO) build -mod vendor -o ../ol
74+
cd $(OL_DIR) && $(GO) build -o ../ol
2275

2376
install: ol
2477
cp ol /usr/local/bin
2578

2679
test-all:
27-
sudo python3 -u test.py
80+
sudo python3 -u ./scripts/test.py --worker_type=sock
81+
sudo python3 -u ./scripts/test.py --worker_type=docker
82+
sudo python3 -u ./scripts/sock_test.py
83+
sudo python3 -u ./scripts/bin_test.py --worker_type=wasm
84+
sudo python3 -u ./scripts/bin_test.py --worker_type=sock
85+
86+
fmt:
87+
#cd src && go fmt ...
88+
cd wasm-worker && cargo fmt
89+
cd bin-functions && cargo fmt
90+
91+
check-fmt:
92+
cd wasm-worker && cargo fmt --check
93+
cd bin-functions && cargo fmt --check
94+
95+
lint:
96+
cd wasm-worker && cargo clippy
97+
cd bin-functions && cargo clippy
98+
pylint scripts --ignore build
2899

29100
clean:
30101
rm -f ol

README.md

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,35 @@ paper](https://www.usenix.org/system/files/conference/hotcloud16/hotcloud16_hend
1111
OpenLambda relies heavily on operations that require root
1212
privilege. To simplify this, we suggest that you run all commands as
1313
the root user. OpenLambda is only actively tested on Ubuntu 20.04 LTS
14-
(AWS AMI `ami-0fb653ca2d3203ac1`, in particular). On Ubuntu 20.04
15-
LTS, you can install the following.
14+
(AWS AMI `ami-0fb653ca2d3203ac1`, in particular).
1615

16+
### Build and Test
17+
Make sure you have all basic dependencies installed:
18+
```
19+
apt install docker.io llvm-11-dev libclang-common-11-dev build-essential python3
1720
```
18-
apt update
19-
apt upgrade -y
20-
apt update
21-
apt remove -y unattended-upgrades
22-
23-
apt install -y python3-pip make gcc docker.io curl
24-
pip3 install boto3
2521

22+
For a recent version of go, run the following:
23+
```
2624
wget -q -O /tmp/go1.17.6.linux-amd64.tar.gz https://dl.google.com/go/go1.17.6.linux-amd64.tar.gz
2725
tar -C /usr/local -xzf /tmp/go1.17.6.linux-amd64.tar.gz
2826
ln -s /usr/local/go/bin/go /usr/bin/go
2927
```
3028

29+
Further, you need to have a recent nightly version of Rust, the wasm32 toolchain, and the `cross` tool installed. The easiest way to do this is.
30+
```
31+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain=nightly
32+
source $HOME/.cargo/env
33+
rustup target add wasm32-unknown-unknown
34+
cargo install cross
35+
```
36+
37+
Finally, add your user to the docker group to enable cross-compilation of native binaries to open-lambda's environment. Do not forget to restart your shell/session afterwards!
38+
```
39+
gpasswd -a $username docker
40+
41+
```
42+
3143
We recommend syncing to a commit that passes our daily tests:
3244
https://s3.us-east-2.amazonaws.com/open-lambda-public/tests.html.
3345

benchmarks/old/numpy.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#! /usr/bin/python3
2+
3+
from time import time, sleep
4+
from subprocess import Popen, call
5+
from tempfile import mkdtemp
6+
7+
import os
8+
import copy
9+
import json
10+
import requests
11+
12+
def post(path, data=None):
13+
return requests.post('http://localhost:5000/'+path, json.dumps(data))
14+
15+
ARG_SIZE=10000
16+
arg = [[x for x in range(ARG_SIZE)] for _ in range(1)]
17+
18+
WASM=True
19+
DOCKER=True
20+
21+
MANY=1000
22+
23+
OLDIR=os.path.abspath("./test-dir")
24+
OL_REGISTRY=os.path.abspath("./test-registry")
25+
26+
if WASM:
27+
print("# WASM")
28+
print("Single")
29+
p = Popen(["./ol-wasm"])
30+
sleep(0.1)
31+
32+
start = time()
33+
post("run/numpy", arg)
34+
end = time()
35+
36+
elapsed = end - start
37+
print("Elapsed: %f s" % (elapsed))
38+
p.kill()
39+
40+
print("Many (cold)")
41+
p = Popen(["./ol-wasm"])
42+
sleep(0.1)
43+
44+
start = time()
45+
for _ in range(MANY):
46+
post("run/numpy", arg)
47+
end = time()
48+
49+
elapsed = end - start
50+
print("Elapsed: %fs (%fs per request)" % (elapsed, elapsed/MANY))
51+
p.kill()
52+
53+
print("Many (warm)")
54+
p = Popen(["./ol-wasm"])
55+
sleep(0.1)
56+
57+
post("run/numpy", arg)
58+
59+
start = time()
60+
for _ in range(MANY):
61+
post("run/numpy", arg)
62+
end = time()
63+
64+
elapsed = end - start
65+
print("Elapsed: %fs (%fs per request)" % (elapsed, elapsed/MANY))
66+
p.kill()
67+
68+
69+
if DOCKER:
70+
def put_conf(conf):
71+
global curr_conf
72+
with open(os.path.join(OLDIR, "config.json"), "w") as f:
73+
json.dump(conf, f, indent=2)
74+
curr_conf = conf
75+
76+
def update_config(**keywords):
77+
with open(os.path.join(OLDIR, "config.json")) as f:
78+
orig = json.load(f)
79+
new = copy.deepcopy(orig)
80+
for k in keywords:
81+
if not k in new:
82+
raise Exception("unknown config param: %s" % k)
83+
if type(keywords[k]) == dict:
84+
for k2 in keywords[k]:
85+
new[k][k2] = keywords[k][k2]
86+
else:
87+
new[k] = keywords[k]
88+
89+
put_conf(new)
90+
91+
92+
print("# DOCKER")
93+
call(["./ol", "kill"])
94+
95+
print("Single")
96+
d = "./test-dir/"# mkdtemp()+"/ol/"
97+
call(["./ol", "new", "-p="+d])
98+
update_config(registry=OL_REGISTRY)
99+
100+
call(["./ol", "worker", "-p="+d, "--detach"])
101+
sleep(0.1)
102+
103+
start = time()
104+
r = post("run/numpy16", arg)
105+
end = time()
106+
if r.status_code != 200:
107+
raise Exception("STATUS %d: %s" % (r.status_code, r.text))
108+
109+
110+
elapsed = end - start
111+
print("Elapsed: %f s" % (elapsed))
112+
call(["./ol", "kill"])
113+
114+
print("Many (cold)")
115+
d = "./test-dir/"# mkdtemp()+"/ol"
116+
call(["./ol", "new", "-p="+d])
117+
update_config(registry=OL_REGISTRY)
118+
119+
p = Popen(["./ol", "worker", "--detach", "-p="+d])
120+
sleep(0.1)
121+
122+
start = time()
123+
for _ in range(MANY):
124+
post("run/numpy16", arg)
125+
end = time()
126+
127+
elapsed = end - start
128+
print("Elapsed: %fs (%fs per req)" % (elapsed, elapsed/MANY))
129+
call(["./ol", "kill"])
130+
131+
print("Many (warm)")
132+
d = "./test-dir/"# mkdtemp()+"/ol"
133+
call(["./ol", "new", "-p="+d])
134+
update_config(registry=OL_REGISTRY)
135+
136+
p = Popen(["./ol", "worker", "--detach", "-p="+d])
137+
sleep(0.1)
138+
139+
post("run/numpy16", arg)
140+
141+
start = time()
142+
for _ in range(MANY):
143+
post("run/numpy16", arg)
144+
end = time()
145+
146+
elapsed = end - start
147+
print("Elapsed: %fs (%fs per req)" % (elapsed, elapsed/MANY))
148+
call(["./ol", "kill"])
149+
150+

0 commit comments

Comments
 (0)