Commit 840692b0 authored by Jason Madden's avatar Jason Madden

Working on some more socket benchmarks

The good news is that current master is about 10-15% faster for
sendall than 1.2.2 was (e.g., 301ws vs 256ms in Python 3.6). udp
sendto is roughly unaffected (within the margins, based on the native
performance). Moving the chunking implementation of sendall to Cython
doesn't show any improvements (so that's not a bottleneck, at least in
these benchmarks).

The "bad" news is that both UDP and (especially) sendall perform much
worse than native (native does about 47ms for sendall). This is
probably related to the fact that we're doing everything in one
process and one thread, and it is CPU bound; the native process can
use 150% CPU or so, but the gevent version cannot. So the comparison
is not directly meaningful.

[skip ci]
parent 62802671
#! /usr/bin/env python
"""
Basic socket benchmarks.
"""
from __future__ import print_function, division, absolute_import
import perf
import gevent
from gevent import socket as gsocket
import socket
import threading
def recvall(sock, _):
while sock.recv(4096):
pass
N = 10
MB = 1024 * 1024
length = 50 * MB
BIG_DATA = b"x" * length
SMALL_DATA = b'x' * 1000
def _sendto(loops, conn, data, to_send=None):
addr = ('127.0.0.1', 55678)
spent_total = 0
sent = 0
to_send = len(data) if to_send is None else to_send
for __ in range(loops):
for _ in range(N):
start = perf.perf_counter()
while sent < to_send:
sent += conn.sendto(data, 0, addr)
spent = perf.perf_counter() - start
spent_total += spent
return spent_total
def _sendall(loops, conn, data):
start = perf.perf_counter()
for __ in range(loops):
for _ in range(N):
conn.sendall(data)
taken = perf.perf_counter() - start
conn.close()
return taken
def bench_native_udp(loops):
conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
return _sendto(loops, conn, SMALL_DATA, len(BIG_DATA))
finally:
conn.close()
def bench_gevent_udp(loops):
conn = gsocket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
return _sendto(loops, conn, SMALL_DATA, len(BIG_DATA))
finally:
conn.close()
def bench_native_thread_default_socketpair(loops):
send, recv = socket.socketpair()
t = threading.Thread(target=recvall, args=(recv, None))
t.daemon = True
t.start()
return _sendall(loops, send, BIG_DATA)
def bench_gevent_greenlet_default_socketpair(loops):
send, recv = gsocket.socketpair()
gevent.spawn(recvall, recv, None)
return _sendall(loops, send, BIG_DATA)
def main():
runner = perf.Runner()
runner.bench_time_func(
'native socketpair sendall',
bench_native_thread_default_socketpair,
inner_loops=N)
runner.bench_time_func(
'gevent socketpair sendall',
bench_gevent_greenlet_default_socketpair,
inner_loops=N)
runner.bench_time_func(
'native udp sendto',
bench_native_udp,
inner_loops=N)
runner.bench_time_func(
'gevent udp sendto',
bench_gevent_udp,
inner_loops=N)
if __name__ == "__main__":
main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment