In this blog post I will describe how to port hyper to use may for asynchronous IO. You will see how easy to porting the thread based code to coroutine based. And also get the high performance that may powers up.
About Hyper
hyper is rust most important Http library that is widely used and it’s trying to give the best asynchronous IO experience for users. Currently hyper is using tokio for async io. But it’s also having a v0.10.x
tag that is thread based which is used by Rocket project.
I will port the thread based version to the coroutine based version for hyper.
The test server is the simple hello example in hyper and I will list all the bench results also.
Bench Settings
Machine Specs:
- Logical Cores: 4 (4 cores x 1 threads)
- Memory: 4gb ECC DDR3 @ 1600mhz
- Processor: CPU Intel(R) Core(TM) i7-3820QM CPU @ 2.70GHz
- Operating System: Ubuntu VirtualBox guest
Bench client
The master that using tokio
Suppose that you have clone the hyper repo in local. Just checkout the master branch of it and run the following commands to start the server
1 | $ git checkout origin/master |
and the bench result is
1 | $ wrk http://127.0.0.1:3000 -d 10 -t 2 -c 200 |
The v0.10.x that using thread
checkout the thread version code and run the server. By default it will spawn enough threads to keep all cpu busy.
1 | $ git checkout origin/0.10.x |
and the bench result is:
1 | $ wrk http://127.0.0.1:3000 -d 10 -t 2 -c 200 |
you can notice that the performance is not as good as previous one because the thread module doesn’t support async IO.
The coroutine based version
now apply the patch to the thread based version. this patch only has a few changes that just replace the necessary std APIs to may APIs and change the thread number to 1000 coroutines.
1 | $ git checkout -b coroutine |
first modify src/hello.rs to using only one thread
1 | may::config().set_io_workers(1).set_stack_size(0x2000); |
and the test result is
1 | $ wrk http://127.0.0.1:3000 -d 10 -t 2 -c 200 |
Ok, it’s almost the same as the thread version.
now change the io workers to 3 and see what happened
1 | may::config().set_io_workers(3).set_stack_size(0x2000); |
bench result is:
1 | $ wrk http://127.0.0.1:3000 -d 10 -t 2 -c 200 |
much better now!
Conclusion
- coroutine based io is much powerful than thread based
- it’s quite easy to port thread based system to coroutine based system
- hyper’s master is really fast with the fact that it runs only on one thread. faster than coroutine based. maybe the whole arch is totally different.