TQ
dev.com

Blog about software development

Subscribe

Porting PHP-CRUD-API to C#

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.

Port of the core functionality

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.

The test environment

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.

PHP-CRUD-API

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.

data-api-dot-net

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.

Expectations and conclusion

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#.