|
15 | 15 | from picows import WSFrame, WSTransport, WSListener, ws_connect, WSMsgType |
16 | 16 | from time import time |
17 | 17 |
|
18 | | -_logger = getLogger(__name__) |
| 18 | + |
| 19 | +try: |
| 20 | + from examples.echo_client_cython import picows_main_cython |
| 21 | +except ImportError: |
| 22 | + picows_main_cython = None |
19 | 23 |
|
20 | 24 |
|
21 | 25 | RPS: Dict[str, List[float]] = {"ssl": [], "plain": []} |
22 | 26 | NAMES: List[str] = [] |
| 27 | +_logger = getLogger(__name__) |
23 | 28 |
|
24 | 29 |
|
25 | 30 | def create_client_ssl_context(): |
@@ -116,7 +121,101 @@ async def aiohttp_main(url: str, data: bytes, duration: int, ssl_context): |
116 | 121 | break |
117 | 122 |
|
118 | 123 |
|
119 | | -if __name__ == '__main__': |
| 124 | +def run_for_websockets_library(plain_url, ssl_url, ssl_context, msg, duration): |
| 125 | + global NAMES, RPS |
| 126 | + _, rps = asyncio.run(websockets_main(plain_url, msg, duration, None)) |
| 127 | + RPS["plain"].append(rps) |
| 128 | + name, rps = asyncio.run(websockets_main(ssl_url, msg, duration, ssl_context)) |
| 129 | + RPS["ssl"].append(rps) |
| 130 | + NAMES.append(name) |
| 131 | + |
| 132 | + |
| 133 | +def run_for_aiohttp_library(plain_url, ssl_url, ssl_context, msg, duration): |
| 134 | + global NAMES, RPS |
| 135 | + _, rps = asyncio.run(aiohttp_main(plain_url, msg, duration, None)) |
| 136 | + RPS["plain"].append(rps) |
| 137 | + name, rps = asyncio.run(aiohttp_main(ssl_url, msg, duration, ssl_context)) |
| 138 | + RPS["ssl"].append(rps) |
| 139 | + NAMES.append(name) |
| 140 | + |
| 141 | + |
| 142 | +def run_picows_client(plain_url, ssl_url, ssl_context, msg, duration): |
| 143 | + global NAMES, RPS |
| 144 | + _, rps = asyncio.run(picows_main(plain_url, msg, duration, None)) |
| 145 | + RPS["plain"].append(rps) |
| 146 | + name, rps = asyncio.run(picows_main(ssl_url, msg, duration, ssl_context)) |
| 147 | + RPS["ssl"].append(rps) |
| 148 | + NAMES.append(name) |
| 149 | + |
| 150 | + |
| 151 | +def run_picows_cython_plain_client(plain_url, ssl_url, ssl_context, msg, duration): |
| 152 | + global NAMES, RPS |
| 153 | + print("Run picows cython plain client") |
| 154 | + rps = asyncio.run(picows_main_cython(plain_url, msg, duration, None)) |
| 155 | + RPS["plain"].append(rps) |
| 156 | + |
| 157 | + |
| 158 | +def run_picows_cython_ssl_client(plain_url, ssl_url, ssl_context, msg, duration): |
| 159 | + global NAMES, RPS |
| 160 | + print("Run picows cython ssl client") |
| 161 | + rps = asyncio.run(picows_main_cython(ssl_url, msg, duration, ssl_context)) |
| 162 | + RPS["ssl"].append(rps) |
| 163 | + |
| 164 | + |
| 165 | +def run_boost_beast_client(args): |
| 166 | + global NAMES, RPS |
| 167 | + |
| 168 | + print("Run boost.beast plain client") |
| 169 | + pr = subprocess.run([args.boost_client, b"0", |
| 170 | + args.host.encode(), |
| 171 | + args.plain_port.encode(), |
| 172 | + args.msg_size, args.duration], |
| 173 | + shell=False, check=True, capture_output=True) |
| 174 | + _, rps = pr.stdout.split(b":", 2) |
| 175 | + RPS["plain"].append(int(rps.decode())) |
| 176 | + |
| 177 | + print("Run boost.beast ssl client") |
| 178 | + pr = subprocess.run([args.boost_client, b"1", |
| 179 | + args.host.encode(), |
| 180 | + args.ssl_port.encode(), |
| 181 | + args.msg_size, args.duration], |
| 182 | + shell=False, check=True, capture_output=True) |
| 183 | + name, rps = pr.stdout.split(b":", 2) |
| 184 | + RPS["ssl"].append(int(rps.decode())) |
| 185 | + NAMES.append("c++ boost.beast") |
| 186 | + |
| 187 | + |
| 188 | +def print_result_and_plot(loop_name, msg_size): |
| 189 | + for k, v in RPS.items(): |
| 190 | + print(k.replace("\n", " "), v) |
| 191 | + |
| 192 | + print("names:", " | ".join(n.replace("\n", " ") for n in NAMES)) |
| 193 | + |
| 194 | + try: |
| 195 | + import matplotlib.pyplot as plt |
| 196 | + |
| 197 | + fig, ax = plt.subplots(layout='constrained') |
| 198 | + |
| 199 | + x = np.arange(len(NAMES)) |
| 200 | + width = 0.25 # the width of the bars |
| 201 | + multiplier = 0 |
| 202 | + |
| 203 | + for cl_type, measurement in RPS.items(): |
| 204 | + offset = width * multiplier |
| 205 | + ax.bar(x + offset, measurement, width, label=cl_type) |
| 206 | + multiplier += 1 |
| 207 | + |
| 208 | + ax.set_ylabel('request/second') |
| 209 | + ax.set_title(f'Echo round-trip performance \n({loop_name}, msg_size={msg_size})') |
| 210 | + ax.set_xticks(x + width, NAMES) |
| 211 | + ax.legend(loc='upper left', ncols=3) |
| 212 | + |
| 213 | + plt.show() |
| 214 | + except ImportError: |
| 215 | + pass |
| 216 | + |
| 217 | + |
| 218 | +def main(): |
120 | 219 | parser = argparse.ArgumentParser(description="Benchmark for the various websocket clients", |
121 | 220 | formatter_class=argparse.ArgumentDefaultsHelpFormatter) |
122 | 221 | parser.add_argument("--host", default="127.0.0.1", help="Server host") |
@@ -146,87 +245,27 @@ async def aiohttp_main(url: str, data: bytes, duration: int, ssl_context): |
146 | 245 | ssl_url = f"wss://{args.host}:{args.ssl_port}/" |
147 | 246 |
|
148 | 247 | if not args.picows_plain_only and not args.picows_ssl_only: |
149 | | - _, rps = asyncio.run(websockets_main(plain_url, msg, duration, None)) |
150 | | - RPS["plain"].append(rps) |
151 | | - name, rps = asyncio.run(websockets_main(ssl_url, msg, duration, ssl_context)) |
152 | | - RPS["ssl"].append(rps) |
153 | | - NAMES.append(name) |
154 | | - |
155 | | - _, rps = asyncio.run(aiohttp_main(plain_url, msg, duration, None)) |
156 | | - RPS["plain"].append(rps) |
157 | | - name, rps = asyncio.run(aiohttp_main(ssl_url, msg, duration, ssl_context)) |
158 | | - RPS["ssl"].append(rps) |
159 | | - NAMES.append(name) |
160 | | - |
161 | | - _, rps = asyncio.run(picows_main(plain_url, msg, duration, None)) |
162 | | - RPS["plain"].append(rps) |
163 | | - name, rps = asyncio.run(picows_main(ssl_url, msg, duration, ssl_context)) |
164 | | - RPS["ssl"].append(rps) |
165 | | - NAMES.append(name) |
| 248 | + run_for_websockets_library(plain_url, ssl_url, ssl_context, msg, duration) |
| 249 | + run_for_aiohttp_library(plain_url, ssl_url, ssl_context, msg, duration) |
| 250 | + run_picows_client(plain_url, ssl_url, ssl_context, msg, duration) |
| 251 | + |
| 252 | + if picows_main_cython is not None: |
| 253 | + NAMES.append("picows\ncython client") |
166 | 254 |
|
167 | | - try: |
168 | | - from examples.echo_client_cython import picows_main_cython |
169 | 255 | if not args.picows_ssl_only: |
170 | | - print("Run picows cython plain client") |
171 | | - rps = asyncio.run(picows_main_cython(plain_url, msg, duration, None)) |
172 | | - RPS["plain"].append(rps) |
| 256 | + run_picows_cython_plain_client(plain_url, ssl_url, ssl_context, msg, duration) |
173 | 257 |
|
174 | 258 | if not args.picows_plain_only: |
175 | | - print("Run picows cython ssl client") |
176 | | - rps = asyncio.run(picows_main_cython(ssl_url, msg, duration, ssl_context)) |
177 | | - RPS["ssl"].append(rps) |
178 | | - |
179 | | - NAMES.append("picows\ncython client") |
180 | | - except ImportError: |
181 | | - pass |
| 259 | + run_picows_cython_ssl_client(plain_url, ssl_url, ssl_context, msg, duration) |
182 | 260 |
|
183 | 261 | if not args.picows_plain_only and not args.picows_ssl_only and args.boost_client is not None: |
184 | | - print("Run boost.beast plain client") |
185 | | - pr = subprocess.run([args.boost_client, b"0", |
186 | | - args.host.encode(), |
187 | | - args.plain_port.encode(), |
188 | | - args.msg_size, args.duration], |
189 | | - shell=False, check=True, capture_output=True) |
190 | | - _, rps = pr.stdout.split(b":", 2) |
191 | | - RPS["plain"].append(int(rps.decode())) |
192 | | - |
193 | | - print("Run boost.beast ssl client") |
194 | | - pr = subprocess.run([args.boost_client, b"1", |
195 | | - args.host.encode(), |
196 | | - args.ssl_port.encode(), |
197 | | - args.msg_size, args.duration], |
198 | | - shell=False, check=True, capture_output=True) |
199 | | - name, rps = pr.stdout.split(b":", 2) |
200 | | - RPS["ssl"].append(int(rps.decode())) |
201 | | - NAMES.append("c++ boost.beast") |
| 262 | + run_boost_beast_client(args) |
202 | 263 |
|
203 | 264 | if args.picows_plain_only or args.picows_ssl_only: |
204 | 265 | exit() |
205 | 266 |
|
206 | | - for k, v in RPS.items(): |
207 | | - print(k.replace("\n", " "), v) |
208 | | - |
209 | | - print("names:", " | ".join(n.replace("\n", " ") for n in NAMES)) |
| 267 | + print_result_and_plot(loop_name, msg_size) |
210 | 268 |
|
211 | | - try: |
212 | | - import matplotlib.pyplot as plt |
213 | 269 |
|
214 | | - fig, ax = plt.subplots(layout='constrained') |
215 | | - |
216 | | - x = np.arange(len(NAMES)) |
217 | | - width = 0.25 # the width of the bars |
218 | | - multiplier = 0 |
219 | | - |
220 | | - for cl_type, measurement in RPS.items(): |
221 | | - offset = width * multiplier |
222 | | - rects = ax.bar(x + offset, measurement, width, label=cl_type) |
223 | | - multiplier += 1 |
224 | | - |
225 | | - ax.set_ylabel('request/second') |
226 | | - ax.set_title(f'Echo round-trip performance \n({loop_name}, msg_size={msg_size})') |
227 | | - ax.set_xticks(x + width, NAMES) |
228 | | - ax.legend(loc='upper left', ncols=3) |
229 | | - |
230 | | - plt.show() |
231 | | - except ImportError: |
232 | | - pass |
| 270 | +if __name__ == '__main__': |
| 271 | + main() |
0 commit comments