Hi% username%
My task was to compare serialization performance for .NET Core and Golang. After searching the Internet, I came across a repository . A simple example of a REST microservice is considered. This is exactly what I need, I thought. After seeing the test results, I was surprised. After looking at the source code, I realized what was wrong. Here's what I didn't like:
- For serialization and deserialization, an array of 3 elements is selected. This is clearly not enough.
- For Golang, all the features of the language are not used, but, as you know, the encoding / json built-in library is slow.
- As a result, the author compares the performance of the kestrel and net / http web servers.
It was these shortcomings that led to a more detailed consideration of performance in the framework of the example described above. I hope you find it interesting to know the results.
Composition and description of software
The source code from the repository above was also taken as a basis. What has been finalized:
- For the server API, fasthttp is used.
- The API server responds with records arrays.
- Each client has several methods for checking.
Modified code is available in the repository .
For clarity, an example JSON response from the server API:
[ { "Id":"id_8299119732867115081", "Name":"name_5541535679032008745", "Time":1566731141 }, ... { "Id":"id_2804604318195309547", "Name":"name_5914011395631118540", "Time":1566731142 } ]
Customers
To evaluate the performance in each service, three methods are implemented:
- receiving data from the server API and sending it without processing [/ testNoProcess].
- receiving data from the server API - deserialization, serialization using reflection and sending [/ testReflection]. For .NETCore, the Newtonsoft.Json package was used, for Golang, encoding / json was used.
- receiving data from the server API - deserialization, serialization without using reflection and sending [/ testNoReflection]. For .NETCore, a Span-based solution was implemented to minimize the number of memory allocations. Golang has a ready-made solution - easyjson library, which has proven itself exclusively on the positive side.
Based on these tests, you can evaluate the relative performance of web servers (kestrel and net / http), the performance drop when processing data using and without reflection for implementations in both languages.
Description of testing methodology
Testing was carried out in several stages in order to evaluate the performance of each language and each implementation.
To create a load, the bombardier utility was selected. The utility was launched with the following parameters: -c 125 –d 120s, which can be interpreted as follows: how to use 125 threads with a test time of 120 seconds.
Performance measurement was carried out in 3 stages:
- RPS API server dimension. The measurements were carried out in order to be able to assess the impact of processing methods on the performance of each method.
- RPS measurement of response processing using reflection.
- Measure RPS response processing without using reflection.
Based on these measurements, data were obtained on the performance of response processing. Utilization of all processor cores was 99.8-100%. For the assessment, the initial data of 10, 30, 100, and 500 records were selected. Arrays of 500 records in size are not common in production, but I was interested to see how each of the languages behaves.
Test stand
All tests were run on a virtual machine running Ubuntu Server 18.04 with all updates for August 2019. It has the following characteristics:
- Processor Core I7-3770K - 4 cores.
- RAM - 4 GB.
For performance comparison, .NET Core 2.2 and Golang 1.12 were installed.
Well, now it's time to move on to the most interesting - the results.
results
Below is a table with the test results.
You can immediately notice that Golang has a more productive web server. The difference is about 12% compared to Kestrel in .NET Core.
Based on the data above, 2 graphs were constructed. Next, you can clearly see the comparison of RPS.
Due to the faster net / http library, Golang shows good results for small data. With an increase in data volume, performance is compared with kestrel.
When using reflection on a small data size, the RPS is approximately the same, taking into account the measurement error. With increasing data size, .NET Core shows more RPS.
When testing without the use of reflection, both languages showed a performance gain. Golang shows better performance because it has initially higher RPS (requests per second) on tests without processing. On small data, the advantage is significant. With the increase in data size, RPS is almost compared. On the biggest test of 500 records, Golang is again ahead.
In tests using reflection, Golang lost on all fronts. The performance drop in the worst-case scenarios was over 60%. Implementing serialization out of the box for performance is generally worthless.
Without reflection, Golang was faster in all tests. And with data growth, the advantage of Golang is only growing. In any case, the refusal to use reflection gives a significant performance increase for both Golang and .NETCore, which, in general, should be expected.
findings
What conclusions can be drawn from this small performance comparison? I would like to formulate this in the form of pros and cons for each of the solutions. Let's start with Golang:
- It has better performance, and it can be further improved, for example, by using fasthttp as a web server.
- Thanks to code generation, it is convenient to use processing methods without using reflection.
- Less memory consumption.
.NET Core also has several advantages:
- Performance is suitable for most cases.
- In my opinion, this is one of the best and most convenient development environments for Visual Studio.
The result can be summarized as follows: if you have a REST API and you are planning a large load, not too complicated business logic, it is better to use Golang, in other cases you can get by with .NET Core. Should I rewrite ready-made solutions from .NET Core to Golang? Everyone will decide for himself.
I hope you find this material useful. All good