.NET Proxy Server — performance testing .NET with K6
Idea
This post is part of bigger project. I always struggled with idea that during development phase I am testing using localhost loopback and actually until close to end of task/project real life problems regarding TCP connection are kind of mystery.
I wanted to create app which can simulate effects like:
- slow connection
- broken connection
- lost packets
Most likely there is already solution for that. But I wanted to learn more about:
- TCP/IP
- low level servers in .NET
- Load testing
Load testing with K6
K6 is a tool which helps to run load testing. Test scenarios are written using js scripts and simplest one could be like this:
To execute this script cli can be used:
— vus defines Virtual Users, to put it simple it is how many parallel runs are executed.
— duration defines how long load testing will take.
Example results might look like this:
There also better UI for presenting results. But with simple 5min setup, test scenario is executed and full information including statistical parameters is retrieved. I found it very convenient in day to day work.
.NET project
Project at this phase is a simple proxy server, which forward TCP packets between client and server.
According to Microsoft Documentation there are currently two API to work with Sockets in .NET:
Simpler, fully asynchronous :
Socket.AcceptAsync Method (System.Net.Sockets) | Microsoft Learn
Performance oriented:
SocketAsyncEventArgs Class (System.Net.Sockets) | Microsoft Learn
Main differnce between those two is focused on reusing resources.
SocketAsyncEventArgs allow to pass data more efficiently, but requires more manual work.
Testing
While I am newbie when it comes to Socket programming, I wanted to test both approaches, and verify how much my proxy is slower/less performant comparing with no proxy at all.
There are three tests:
- Baseline — simple HTTP server running one HTML web page, no proxy at all (NGINX in docker container)
- Async API — First approach using GitHub — mes1234/Muddler at poc/proxy
- SocketAsyncEventArgs — Perfomance oriented: GitHub — mes1234/Muddler at poc/proxy_events
All of theme were using the same test scenario as in introduction to K6.
Results
Baseline:
Async API:
SocketAsyncEventArgs API:
Comparison:
- Baseline: 1775 request/sec
- Async API: 415 request/sec — ~76% downgrade
- SocketAsyncEventArgs: 1644 requests/sec — 8% downgrade
Summary
8% downgrade is promising starting point. Most likely code can be optimized. Biggest benefit is that there is clear metric to verify performance under real life load, not just simple request run manually.
Please fell free to comment.