ekr / minq

A simple Go implementation of QUIC
MIT License
98 stars 16 forks source link

Minq is slow #29

Closed pietdevaere closed 6 years ago

pietdevaere commented 6 years ago

During my tests sending a heartbeat message every 10ms, I measured to following execution times for server.Input().

[...]
--> It took me 24.376149ms to process a udp packet
--> It took me 12.757307ms to process a udp packet
--> It took me 13.639388ms to process a udp packet
--> It took me 16.154656ms to process a udp packet
--> It took me 19.923801ms to process a udp packet
[...]

This seems waaaay to long. I'll do a profile on the code tomorrow to see what is taking so long. I suspect it will be the linear searches through the frames and sendqueues. See also my remarks in #28

pietdevaere commented 6 years ago

cpu trace of a minq server, processing heartbeats at 100 Hz: https://devae.re/s/minq_server_cpu_trace.svg

pietdevaere commented 6 years ago

So there were two problems.

The first one was that when generating the ACK ranges, the code would iterate over ALL packets it previously received. Also those that had been double acked ages ago. I solved this by introducing a minNotAcked2 variable to stop the iteration. After doing that the profile web looked like [1], reducing the share of prepareAckRange from 62% to 3.5%.

The second problem that for every packet acked in an incomming ACK frame, an expensive hashmap lookup would be performed. By comparing pn to minNotAcked2 before doing this lookup, I managed to reduce the share of processAckFrame from 84% to 1.3%

[1] https://devae.re/s/minq_server_cpu_trace_prepare_ack_fixed.svg [2] https://devae.re/s/minq_server_cpu_trace_setack2_fixed.svg