Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up performance test #149

Merged
merged 1 commit into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions perf-tests/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
# Set destination for COPY


# Download Go modules
FROM golang:1.18-alpine
WORKDIR /app

WORKDIR /app

COPY go.mod ./
COPY go.sum ./
RUN go mod download
COPY *.go ./
COPY server.crt /app/server.crt
COPY server.key /app/server.key
COPY server.go ./

RUN go build -o /enclave-server

Expand Down
70 changes: 46 additions & 24 deletions perf-tests/README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,67 @@
## What is in this folder?
## What is in this directory?

We have done several runs to evaluate performace of enclaver/nitro-enclaves. As part of these tests I have created a simple GO server that works using a self signed SSL certificate and does a naive crypto operation.

API used to test - https://localhost:8082/hello
Several tests have been done to evaluate performance of
enclaver/nitro-enclaves. As part of these tests, a simple Go server
runs within the enclave and burns some CPU every time the endpoint
(`http://localhost:8082/busy`) is fetched.

## Instance Setup

1. Provision a new nitro instance and follow the steps here to setup up nitro_allocator.yaml file https://edgebit.io/enclaver/docs/0.x/guide-first/
1. Provision a new nitro instance (`c6a.2xlarge` or `c6g.xlarge` is
recommended) and follow the [first-enclave guide][first-enclave] to
setup up the nitro_allocator.yaml file.

2. Modify the file `/etc/nitro_enclaves/allocator.yaml`, setting
`cpu_count` to `4`:

```console
$ sudo sed --in-place 's/cpu_count: 2/cpu_count: 4/g' /etc/nitro_enclaves/allocator.yaml
```

2. Modify the file `/etc/nitro_enclaves/allocator.yaml` to `cpu_count: 4`
3. Restart the nitro-allocator service:

3. Restart the nitro-allocator service using `sudo systemctl restart nitro-enclaves-allocator.service`
```console
$ sudo systemctl restart nitro-enclaves-allocator.service
```

[first-enclave]: ../docs/guide-first.md

## JMeter setup

SSH into your machine and run the following commands

```
mkdir jmeter
cd jmeter
wget https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-5.5.tgz
tar -xf apache-jmeter-5.5.tgz
sudo amazon-linux-extras install java-openjdk11
```console
$ mkdir jmeter
$ cd jmeter
$ wget --quiet https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-5.5.tgz
$ tar --extract --file apache-jmeter-5.5.tgz
$ sudo yum install --assumeyes java-11-amazon-corretto-headless
```

## Running the tests

The script `./run_in_enclave.sh` contains the commands to start the nitro enclave.

Comment out the 4vcpu part of the script if you are using 2cvpu to start enclaves and vice-versa.
[`run_enclave.sh`](run_enclave.sh) contains the commands to start the
nitro enclave. The first argument specifies the number of vCPUs to use
for the enclave (defaults to `4`). [`run_jmeter.sh`](run_jmeter.sh)
runs the JMeter test suite and prints the summary of the results.

1. Start the enclave using the command `./run_in_enclave.sh`
2. Run JMeter tests using `./run_jmeter_test.sh`
The two scripts can be invoked in one line:

```console
$ sudo ./run_enclave.sh && ./run_jmeter.sh
```

## Sample results
## Sample results

With 4vCPUs -
`summary = 12000 in 00:00:42 = 283.7/s Avg: 155 Min: 12 Max: 2707 Err: 0 (0.00%)`
With four vCPUs:
```
summary = 12000 in 00:00:42 = 283.7/s Avg: 155 Min: 12 Max: 2707 Err: 0 (0.00%)
```

With 2vCPUs - `summary = 12000 in 00:00:41 = 290.3/s Avg: 108 Min: 14 Max: 1755 Err: 0 (0.00%)`
With two vCPUs:
```
summary = 12000 in 00:00:41 = 290.3/s Avg: 108 Min: 14 Max: 1755 Err: 0 (0.00%)
```

As you can see there is no significant difference in TPS by increasing the number of vCPUs.
At the moment, there is no significant difference in TPS by increasing
the number of vCPUs.
13 changes: 0 additions & 13 deletions perf-tests/enclaver_2vcpu.yaml

This file was deleted.

13 changes: 0 additions & 13 deletions perf-tests/enclaver_4vcpu.yaml

This file was deleted.

44 changes: 0 additions & 44 deletions perf-tests/go.sum

This file was deleted.

5 changes: 2 additions & 3 deletions perf-tests/Test Plan.jmx → perf-tests/plan.jmx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@
</elementProp>
<stringProp name="HTTPSampler.domain">localhost</stringProp>
<stringProp name="HTTPSampler.port">8082</stringProp>
<stringProp name="HTTPSampler.protocol">https</stringProp>
<stringProp name="HTTPSampler.protocol">http</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<!-- <stringProp name="HTTPSampler.path">/abc/versions/xyz/encrypt/helloFormOUtised</stringProp> -->
<stringProp name="HTTPSampler.path">/hello</stringProp>
<stringProp name="HTTPSampler.path">/busy</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
Expand Down
38 changes: 38 additions & 0 deletions perf-tests/run_enclave.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env bash

VCPUS="${1:-4}"

docker stop nitro_enclave

set -e

image_name=enclave_image_${VCPUS}vcpu

docker rmi --force docker-go ${image_name}
docker build -t docker-go .

config=$(mktemp)
trap "rm --force ${config}" EXIT

cat > ${config} <<- EOF
version: v1
name: ${VCPUS}vcpu
target: ${image_name}
sources:
app: docker-go
defaults:
memory_mb: 3000
cpu_count: ${VCPUS}
egress:
allow:
- "**"
ingress:
- listen_port: 8082
EOF

enclaver build -f ${config}
docker run --detach --rm \
--name=nitro_enclave \
--device=/dev/nitro_enclaves:/dev/nitro_enclaves:rw \
--publish=8082:8082 \
${image_name}
16 changes: 0 additions & 16 deletions perf-tests/run_in_enclave.sh

This file was deleted.

5 changes: 5 additions & 0 deletions perf-tests/run_jmeter.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh

~/jmeter/apache-jmeter-5.5/bin/jmeter --nongui --testfile plan.jmx | \
grep "summary ="
echo
3 changes: 0 additions & 3 deletions perf-tests/run_jmeter_test.sh

This file was deleted.

9 changes: 0 additions & 9 deletions perf-tests/server.crt

This file was deleted.

63 changes: 13 additions & 50 deletions perf-tests/server.go
Original file line number Diff line number Diff line change
@@ -1,60 +1,23 @@
package main

import (
// "fmt"
// "io"
"net/http"
"log"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
"fmt"
"log"
"net/http"
)

var bytes = []byte{35, 46, 57, 24, 85, 35, 24, 74, 87, 35, 88, 98, 66, 32, 14, 05}
// This should be in an env file in production
const MySecret string = "abc&1*~#^2^#s0^=)^^7%b34"
func Encode(b []byte) string {
return base64.StdEncoding.EncodeToString(b)
func HelloServer(w http.ResponseWriter, req *http.Request) {
busy := 0
for i := 0; i < 1000000; i++ {
busy += i
}
fmt.Fprintf(w, "Busy calculation: %d", busy)
}

func Encrypt(text, MySecret string) (string, error) {
block, err := aes.NewCipher([]byte(MySecret))
func main() {
http.HandleFunc("/busy", HelloServer)
err := http.ListenAndServe(":8082", nil)
if err != nil {
return "", err
log.Fatal("ListenAndServe: ", err)
}
plainText := []byte(text)
cfb := cipher.NewCFBEncrypter(block, bytes)
cipherText := make([]byte, len(plainText))
cfb.XORKeyStream(cipherText, plainText)
return Encode(cipherText), nil
}

func HelloServer(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte("This is an example server.\n"))
StringToEncrypt := "Encrypting this string"
certificates := req.TLS.PeerCertificates
if len(certificates) > 0 {
fmt.Println("Found client certificate")
}

// To encrypt the StringToEncrypt
encText, err := Encrypt(StringToEncrypt, MySecret)
if err != nil {
fmt.Println("error encrypting your classified text: ", err)
}
// fmt.Println(encText)
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte(encText))
// fmt.Fprintf(w, "This is an example server.\n")
// io.WriteString(w, "This is an example server.\n")
}

func main() {
http.HandleFunc("/hello", HelloServer)
err := http.ListenAndServeTLS(":8082", "/app/server.crt", "/app/server.key", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
9 changes: 0 additions & 9 deletions perf-tests/server.key

This file was deleted.

Loading