Skip to content

Commit

Permalink
Cleanups and update benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
taras committed Aug 23, 2024
1 parent 320ec4a commit 3946a65
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 17 deletions.
Binary file modified docs/source/_static/picows_benchmark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions examples/echo_client_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def on_ws_frame(self, transport: WSTransport, frame: WSFrame):
self._cnt += 1

if time() - self._start_time >= duration:
RPS["picows(python)"] = int(self._cnt / duration)
RPS["picows\npython client"] = int(self._cnt / duration)
self._transport.disconnect()
else:
self._transport.send(WSMsgType.BINARY, msg)
Expand All @@ -79,7 +79,7 @@ async def websockets_main(endpoint: str, msg: bytes, duration: int, ssl_context)
else:
await websocket.send(msg)

RPS[f"websockets({websockets.__version__})"] = int(cnt / duration)
RPS[f"websockets\n{websockets.__version__}"] = int(cnt / duration)


async def aiohttp_main(url: str, data: bytes, duration: int, ssl_context) -> None:
Expand All @@ -96,7 +96,7 @@ async def aiohttp_main(url: str, data: bytes, duration: int, ssl_context) -> Non
if msg.type == aiohttp_WSMsgType.BINARY:
cnt += 1
if time() - start_time >= duration:
RPS[f"aiohttp({aiohttp.__version__})"] = int(cnt/duration)
RPS[f"aiohttp\n{aiohttp.__version__}"] = int(cnt/duration)
await ws.close()
else:
await ws.send_bytes(data)
Expand Down Expand Up @@ -131,7 +131,7 @@ async def aiohttp_main(url: str, data: bytes, duration: int, ssl_context) -> Non
if os.name != 'nt':
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop_name = f"uvloop({uvloop.__version__})"
loop_name = f"uvloop\n{uvloop.__version__}"

ssl_context = create_client_ssl_context() if args.url.startswith("wss://") else None

Expand All @@ -142,11 +142,11 @@ async def aiohttp_main(url: str, data: bytes, duration: int, ssl_context) -> Non
try:
from examples.echo_client_cython import picows_main_cython
picows_cython_rps = asyncio.run(picows_main_cython(args.url, msg, duration, ssl_context))
RPS["picows(cython)"] = picows_cython_rps
RPS["picows\ncython client"] = picows_cython_rps
except ImportError:
pass

RPS["c++ boost.beast(sync)"] = 42489
RPS["c++ boost.beast\nsync client"] = 56878

for k, v in RPS.items():
print(k, v)
Expand Down
15 changes: 4 additions & 11 deletions picows/picows.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -462,8 +462,6 @@ cdef class WSTransport:

cdef bytes _prepare_frame_in_external_buffer(self, WSMsgType msg_type, uint8_t* msg_ptr, size_t msg_length, bint fin, bint rsv1):
cdef:
# Just fin byte and msg_type
# No support for rsv/compression
uint8_t* header_ptr = msg_ptr
uint64_t extended_payload_length_64
uint32_t mask = <uint32_t> rand() if self._is_client_side else 0
Expand Down Expand Up @@ -512,11 +510,9 @@ cdef class WSTransport:
msg_ptr = b""
msg_length = 0
elif PyBytes_CheckExact(message):
# Just a small optimization for bytes type as the most used type for sending data
msg_ptr = PyBytes_AS_STRING(message)
msg_length = PyBytes_GET_SIZE(message)
elif PyByteArray_CheckExact(message):
# Just a small optimization for bytes type as the most used type for sending data
msg_ptr = PyByteArray_AS_STRING(message)
msg_length = PyByteArray_GET_SIZE(message)
else:
Expand All @@ -527,8 +523,6 @@ cdef class WSTransport:
PyBuffer_Release(&msg_buffer)

cdef:
# Just fin byte and msg_type
# No support for rsv/compression
uint8_t first_byte = <uint8_t>msg_type
uint8_t second_byte = 0x80 if self._is_client_side else 0
uint32_t mask = <uint32_t>rand() if self._is_client_side else 0
Expand Down Expand Up @@ -724,8 +718,9 @@ cdef class WSProtocol:
const char * ptr = PyBytes_AS_STRING(data)
size_t sz = PyBytes_GET_SIZE(data)

# Leave some space for simd parsers like simdjson, they required extra space beyond normal data to make sure
# that vector reads don't cause access violation
# Leave some space for simd parsers like simdjson, they require extra
# space beyond normal data to make sure that vector reads
# don't cause access violation
if self._buffer.size - self._f_new_data_start_pos < (sz + 64):
self._buffer.resize(self._f_new_data_start_pos + sz + 64)

Expand Down Expand Up @@ -996,12 +991,10 @@ cdef class WSProtocol:
self._f_has_mask = (second_byte >> 7) & 1
self._f_payload_length_flag = second_byte & 0x7F

# Control frames MUST have a payload
# length of 125 bytes or less
if self._f_msg_type > 0x7 and self._f_payload_length_flag > 125:
raise _WSParserError(
WSCloseCode.PROTOCOL_ERROR,
"Control frame payload cannot be " "larger than 125 bytes",
"Control frame payload cannot be larger than 125 bytes",
)

self._f_curr_state_start_pos += 2
Expand Down

0 comments on commit 3946a65

Please sign in to comment.