wsproto icon indicating copy to clipboard operation
wsproto copied to clipboard

over 10% regression in small message performance

Open belm0 opened this issue 5 years ago • 2 comments

using the newly minted bench/connection.py with some tweaks:

$ pip install wsproto==0.14.1 wsaccel
$ python bench/connection.py
4.636s elapsed, 93usec per iteration

$ pip install wsproto==1.0.0
$ python bench/connection.py
5.192s elapsed, 104usec per iteration

Benchmark patch follows. It should probably be expanded with command line args for count, message size, etc.

diff --git a/bench/connection.py b/bench/connection.py
index 6585944..bc10bfa 100644
--- a/bench/connection.py
+++ b/bench/connection.py
@@ -5,16 +5,16 @@ from typing import List
 import wsproto
 
 random_seed = 0
-mu = 125 * 1024
-sigma = 75 * 1024
-iterations = 5000
+mu = 125 #* 1024
+sigma = 75 #* 1024
+iterations = 50000
 per_message_deflate = False
 
 
 rand = random.Random(random_seed)
 
 
-client_extensions: List[wsproto.extensions.Extension] = []
+#client_extensions: List[wsproto.extensions.Extension] = []
 if per_message_deflate:
     pmd = wsproto.extensions.PerMessageDeflate()
     offer = pmd.offer()
@@ -23,11 +23,11 @@ if per_message_deflate:
     client_extensions.append(pmd)
 client = wsproto.connection.Connection(
     wsproto.ConnectionType.CLIENT,
-    extensions=client_extensions,
+    #extensions=client_extensions,
 )
 
 
-server_extensions: List[wsproto.extensions.Extension] = []
+#server_extensions: List[wsproto.extensions.Extension] = []
 if per_message_deflate:
     pmd = wsproto.extensions.PerMessageDeflate()
     offer = pmd.offer()
@@ -35,23 +35,24 @@ if per_message_deflate:
     pmd.accept(offer)
 server = wsproto.connection.Connection(
     wsproto.ConnectionType.SERVER,
-    extensions=server_extensions,
+    #extensions=server_extensions,
 )
 
 
 start = time.perf_counter()
 for i in range(iterations):
     client_msg = b"0" * max(0, round(rand.gauss(mu, sigma)))
-    client_out = client.send(wsproto.events.BytesMessage(client_msg))
+    client_out = client.send(wsproto.events.BytesMessage(data=client_msg))
     server.receive_data(client_out)
     for event in server.events():
         pass
 
     server_msg = "0" * max(0, round(rand.gauss(mu, sigma)))
-    server_out = server.send(wsproto.events.TextMessage(server_msg))
+    server_out = server.send(wsproto.events.TextMessage(data=server_msg))
     client.receive_data(server_out)
     for event in client.events():
         pass
 end = time.perf_counter()
 
-print(f"{end - start:.4f}s")
+dt = end - start
+print(f"{dt:.3f}s elapsed, {dt/iterations * 1e6:.0f}usec per iteration")

belm0 avatar Nov 25 '20 10:11 belm0

I'm not sure what a possible solution is here, I don't think wsaccel is an option.

pgjones avatar Jan 10 '21 19:01 pgjones

Has anyone done performance profiling on wsproto?

belm0 avatar Jan 10 '21 22:01 belm0

As wsaccel is no longer maintained (regression came from switching away) I think there is no clear solution to reverse this. However, I'm now testing a mypyc compiled wsproto that could provide a solution.

pgjones avatar Aug 23 '22 14:08 pgjones