Performance Comparison of Java FunTester, Go net/http, and fasthttp HTTP Servers
This article compares the performance of three HTTP server implementations—Java FunTester, Go's net/http, and the fasthttp library—by measuring QPS, CPU usage, and memory consumption across 1, 5, and 10 concurrent threads, and concludes that fasthttp consistently outperforms the others.
Test Cases
The previous post evaluated three HTTP client libraries (Java & Go) and concluded that fasthttp > FunTester > http in client performance. This article examines the server‑side performance of services built with those three frameworks.
The test plan measures QPS, CPU usage, and memory consumption of each server under different thread counts. Earlier Mac‑local HTTP service limits dropped after OS upgrades, so the focus is on comparative load testing rather than absolute limits.
Test Script
The test uses FunTester’s standard template com.funtester.frame.thread.RequestThreadTimes . The script (simplified) is shown below:
static String url = "http://localhost:8001/test";
public static void main(String[] args) {
HttpGet httpGet = getHttpGet(url);
RUNUP_TIME = 0;
RequestThreadTimes requestThreadTimes = new RequestThreadTimes(httpGet, 20000);
new Concurrent(requestThreadTimes, 20, "FunTester").start();
}Thread count, warm‑up time, and request numbers are hard‑coded.
Server Implementations
All servers return the plain string "Have Fun ~ Tester !" as the response.
FunTester (Java)
Implemented with the moco_FunTester framework (a thin wrapper around mocoAPI). This framework previously achieved 120k QPS.
static void main(String[] args) {
def server = getServerNoLog(8001)
server.response("Have Fun ~ Tester !")
def run = run(server)
waitForKey("fan")
run.stop()
}Go net/http
A minimal Go HTTP server using the standard library:
func TestHttpSer2(t *testing.T) {
http.Handle("/test", &indexHandler{content: "Have Fun ~ Tester !"})
http.ListenAndServe(":8001", nil)
}Go fasthttp
The same endpoint implemented with the fasthttp library and router:
func TestFastSer2(t *testing.T) {
address := ":8001"
router := fasthttprouter.New()
router.GET("/test", func(ctx *fasthttp.RequestCtx) {
ctx.Response.SetBody([]byte("Have Fun ~ Tester !"))
})
fasthttp.ListenAndServe(address, router.Handler)
}Measured Results
1 Thread
Framework
CPU
Memory
QPS
FunTester
39.85
212.2 MB
17073
Go(net/http)
93.72
16.5 MB
14124
Go(/valyala/fasthttp)
61.53
12.8 MB
17502
5 Threads
Framework
CPU
Memory
QPS
FunTester
185.75
181.8 MB
64690
Go(net/http)
311.89
18.4 MB
48608
Go(/valyala/fasthttp)
186.85
15.1 MB
67001
10 Threads
Framework
CPU
Memory
QPS
FunTester
276.91
161.0 MB
75795
Go(net/http)
479.69
19.0 MB
62534
Go(/valyala/fasthttp)
269.33
16.6 MB
75723
Conclusion
Overall, the server‑side ranking matches the client‑side results: fasthttp > FunTester > net/http. Go’s net/http consumes more memory and CPU, resulting in slightly lower QPS. The superior performance of fasthttp stems from its object‑pool design, though developers should be aware of the associated pitfalls when using it in high‑throughput services.
FunTester
10k followers, 1k articles | completely useless
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.