16 Apr 2016 - by 'Maurits van der Schee'
I have started porting PHP-CRUD-API to C#. I am doing this for the expected improved performance and also to open up this tool for people that do not program PHP. I am considering a Java and a Go port after this C# port. Porting to C# has turned out to be more work than I expected, partly because I'm not that fluid in C#. I noted that it is very good for the code quality as I am forced to re-read and re-consider every line of code I've written.
Because the port, named data-api-dot-net, is not yet finished and my motivation was dropping, I decided to do some preliminary performance tests. I took the core of PHP-CRUD-API (55 lines of code) and compared that to the same functionality implemented in C#. This way I was able to have a first look at the performance difference between the two implementations.
I ran both tests 100k times using Apache Bench and both times the CPU was (almost) 100% loaded with lots of I/O wait. Both tests were executed on the same machine: an i7 Intel NUC containing low voltage laptop components. The machine has 4 cores and I only needed 8 concurrent threads to ensure 100% CPU load. I am running Linux (Ubuntu 15.10) with MySQL 5.6.28 and I have "innodb_flush_log_at_trx_commit=0
" in "mysqld.cnf
" for maximum insert performance. To ensure I was comparing apples to apples I created a simple "Hello world" implementation in both environments and they both performed about 25k requests per second.
First I tried reading a single record at maximum speed on PHP 5.6.11 (with Zend OPcache v7.0.6) using "php -S localhost:8000 >/dev/null 2>&1
" to run the code.
maurits@nuc:~$ ab -c 8 -n 100000 http://localhost:8000/extras/core.php/posts/2
This is ApacheBench, Version 2.3 <$Revision: 1638069 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software:
Server Hostname: localhost
Server Port: 8000
Document Path: /extras/core.php/posts/2
Document Length: 186 bytes
Concurrency Level: 8
Time taken for tests: 31.214 seconds
Complete requests: 100000
Failed requests: 0
Total transferred: 32300000 bytes
HTML transferred: 18600000 bytes
Requests per second: 3203.68 [#/sec] (mean)
Time per request: 2.497 [ms] (mean)
Time per request: 0.312 [ms] (mean, across all concurrent requests)
Transfer rate: 1010.54 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 2
Processing: 0 2 0.3 2 15
Waiting: 0 2 0.3 2 15
Total: 1 2 0.3 2 15
Percentage of the requests served within a certain time (ms)
50% 2
66% 2
75% 3
80% 3
90% 3
95% 3
98% 3
99% 4
100% 15 (longest request)
maurits@nuc:~$
As you can see I was able to do around 3200 requests per second executing this PHP script.
Second I tried reading the same single record at maximum speed, using Mono C# v3.2.8 and evhttp-sharp.
maurits@nuc:~$ ab -c 8 -n 100000 http://localhost:8000/posts/2
This is ApacheBench, Version 2.3 <$Revision: 1638069 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software:
Server Hostname: localhost
Server Port: 8000
Document Path: /posts/2
Document Length: 112 bytes
Concurrency Level: 8
Time taken for tests: 18.036 seconds
Complete requests: 100000
Failed requests: 0
Total transferred: 19900000 bytes
HTML transferred: 11200000 bytes
Requests per second: 5544.56 [#/sec] (mean)
Time per request: 1.443 [ms] (mean)
Time per request: 0.180 [ms] (mean, across all concurrent requests)
Transfer rate: 1077.51 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 3
Processing: 0 1 0.7 1 25
Waiting: 0 1 0.7 1 25
Total: 0 1 0.7 1 25
Percentage of the requests served within a certain time (ms)
50% 1
66% 1
75% 2
80% 2
90% 2
95% 2
98% 3
99% 3
100% 25 (longest request)
maurits@nuc:~$
As you can see I was able to do around 5500 requests per second executing this similar C# code.
These test results really motivate me to port PHP-CRUD-API to more languages as it can give the performance a huge boost (70% in this test). As more code is ported I expect this difference to become even bigger. The full script in PHP performs 950 requests per second on my machine. I really wonder how the full implementation performs in C#.
PS: Liked this article? Please share it on Facebook, Twitter or LinkedIn.