Closed salsal97 closed 2 years ago
This test was run on an ubuntu 20.04 azure DC-series VMs.
I'm assuming these are the machines that have only 128MB of EPC (Enclave Page Cache)? You can easily check it via the is-sgx-available
utility that comes with Gramine.
The size of EPC is very important for performance. You can read through this docs, for example: https://gramine.readthedocs.io/en/latest/devel/performance.html#choice-of-sgx-machine
There are also several other subtle issues with SGX machines that can contribute to bad performance. For example, some older SGX machines do not have RDTSC instruction enabled inside SGX enclaves -- this also deteriorates enclave performance.
I am wondering if this is the most efficient way to run the redis server on gramine?
A typical way to test Redis is to run the client (redis_benchmark
) on another machine, connected via 1Gb or 10Gb Ethernet link with your main SGX machine (where redis-server
runs). This setup emulates the real-world environments where applications from the Internet/other machines on the cluster connect to the Redis server.
Because you run both the client and the server on the same machine, you don't account for the overhead/latency of the network link. This setup does not reflect how things work in reality, and thus shows unnecessarily bad performance.
Are there any other configurations I might benefit from tweaking, to make this benchmark test run faster?
redis-benchmark
by default updates a single key-value pair (if I remember correctly). In reality, Redis servers hold thousands and millions of key-value pairs. Also, the typical access pattern for Redis is 80% reads and 20% writes (or 95% reads and 5% writes) -- it depends on what kind of workload you want to simulate with your tests. There are many resources on the Internet on how to do proper benchmarking of databases, including how to benchmark Redis. For example, the classic one: https://redis.io/topics/benchmarks
If you want to get the best performance of Redis in Gramine-SGX, probably the best configuration will be something like this:
The above configuration will probably give you something like 5% overhead of Gramine-SGX in comparison to native (this is just my projection, I have no real numbers to back up my hypothesis). But please note that my proposed setup may be not too realistic (especially the 1Gbps network link -- in an enterprise cluster, the network link would be at least 10Gbps I guess).
Hi,
Thank you for your response. I'm running this on an icelake machine, the output of is-sgx-available
is here -
$ is-sgx-available
SGX supported by CPU: true
SGX1 (ECREATE, EENTER, ...): true
SGX2 (EAUG, EACCEPT, EMODPR, ...): true
Flexible Launch Control (IA32_SGXPUBKEYHASH{0..3} MSRs): true
SGX extensions for virtualizers (EINCVIRTCHILD, EDECVIRTCHILD, ESETCONTEXT): false
Extensions for concurrent memory management (ETRACKC, ELDBC, ELDUC, ERDINFO): false
CET enclave attributes support (See Table 37-5 in the SDM): false
Key separation and sharing (KSS) support (CONFIGID, CONFIGSVN, ISVEXTPRODID, ISVFAMILYID report fields): true
Max enclave size (32-bit): 0x80000000
Max enclave size (64-bit): 0x100000000000000
EPC size: 0x200000000
SGX driver loaded: true
AESMD installed: true
SGX PSW/libsgx installed: true
Going through the factors for best performance here,
redis-benchmark -q -t set -h 127.0.0.1 -p 6379 -r 100000 -d 20 -c $NUM_CLIENT -n $REQUESTS
. I tried datalen values 20, 200, 2048 and 20000, & varied the number of clients and requests - but they did not make a huge difference on the performance. @salsal97 There is a memtier
benchmark that I used when doing some Redis benchmarking -- this benchmark supports different ratio of reads/writes, and many other interesting knobs. See https://github.com/RedisLabs/memtier_benchmark.
The overhead of 2.75 is too much for a proper Icelake server. Something doesn't add up here.
What is the size of RAM on your machine? You can dump the output of free -h
command.
When you enable warnings in the Gramine log (by adding loader.log_level = "warning"
in the Redis manifest file), do you see the message all RDTSC/RDTSCP instructions are emulated (imprecisely) via gettime() syscall
?
since I am using an azure VM, I cannot connect the client on a different machine - is there any way to get around this?
You can make this Azure VM visible to the outside world, by asking for a public IP (there is a checkbox for this somewhere, when you create a VM in Azure portal). And then you can just connect to this public IP from any machine (like your local laptop).
Alternatively, you can create two VMs in an Azure cluster.
Hi @dimakuv, thanks again for your response.
Also, I'm guessing changing the connection between the client and server would not make a huge difference since the same test was performed with the same conditions for native and then compared.. I'm mostly looking for if there are any release mode configuration settings on gramine or anything else of that sort that would possibly have optimizations included and might improve performance?
I'm mostly looking for if there are any release mode configuration settings on gramine or anything else of that sort that would possibly have optimizations included and might improve performance?
@salsal97 I hope that you either used the Gramine package (as described in https://gramine.readthedocs.io/en/latest/quickstart.html) or built Gramine from GitHub sources with --buildtype=release
(as described in https://gramine.readthedocs.io/en/latest/devel/building.html#id2). In both these cases you'll get a release version of Gramine (i.e., optimized for performance).
For different runtime performace optimizations, please read through https://gramine.readthedocs.io/en/latest/devel/performance.html.
I just tried to add the following optimizations to my local redis-server.manifest.template
:
libos.check_invalid_pointers = false
sgx.preheat_enclave = true
sgx.rpc_thread_num = 8 # but please note that this comes at the cost of additional CPU cores!
This gave me a huge performance boost in my local run. Before these optimizations, I observed 2x overhead. With these optimizations, I observe no overhead.
@dimakuv
I did use the gramine installation from the quickstart instructions, so we are covered on that front.
Thank you for the manifest suggestions. This brought the performance of the gramine redis benchmark test up considerably and its now running more or less on par with native, even faster in some cases.
Great to hear that your Redis runs with an expected perf overhead now :) I am closing this issue, but if you think there is still something to discuss, feel free to reopen it.
Description of the problem
On comparing the performance of the gramine redis server with native using the redis-benchmark tool, gramine comes to be almost 2.75 times slower than running with its native counterpart. This test was run on an ubuntu 20.04 azure DC-series VMs.
Steps to reproduce
Followed quickstart instructions to install gramine using apt -
Expected results
Results are as expected; however, I am wondering if this is the most efficient way to run the redis server on gramine? Are there any other configurations I might benefit from tweaking, to make this benchmark test run faster? Interested in any input.
Actual results
NA