File: bench_socket.py

package info (click to toggle)
python-gevent 24.11.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,364 kB
  • sloc: python: 138,768; ansic: 87,807; sh: 12,548; makefile: 2,379; javascript: 108
file content (155 lines) | stat: -rw-r--r-- 3,784 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#! /usr/bin/env python
"""
Basic socket benchmarks.
"""
from __future__ import print_function, division, absolute_import

import os
import sys


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 _do_sendall(loops, send, recv):
    for s in send, recv:
        os.set_inheritable(s.fileno(), True)
    pid = os.fork()
    if not pid:
        send.close()
        recvall(recv, None)
        recv.close()
        sys.exit()
        return 0
    else:
        try:
            return _sendall(loops, send, BIG_DATA)
        finally:
            send.close()
            recv.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 bench_gevent_forked_socketpair(loops):
    send, recv = gsocket.socketpair()
    return _do_sendall(loops, send, recv)

def bench_native_forked_socketpair(loops):
    send, recv = socket.socketpair()
    return _do_sendall(loops, send, recv)


def main():
    if '--profile' in sys.argv:
        import cProfile
        import pstats
        import io
        pr = cProfile.Profile()
        pr.enable()
        for _ in range(2):
            bench_gevent_forked_socketpair(2)
        pr.disable()
        s = io.StringIO()
        sortby = 'cumulative'
        ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
        ps.print_stats()
        print(s.getvalue())
        return
    runner = perf.Runner()

    runner.bench_time_func(
        'gevent socketpair sendall greenlet',
        bench_gevent_greenlet_default_socketpair,
        inner_loops=N)

    runner.bench_time_func(
        'native socketpair sendall thread',
        bench_native_thread_default_socketpair,
        inner_loops=N)

    runner.bench_time_func(
        'gevent socketpair sendall fork',
        bench_gevent_forked_socketpair,
        inner_loops=N)

    runner.bench_time_func(
        'native socketpair sendall fork',
        bench_native_forked_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()