Allow use of orjson instead of json

The difference in speed seems negligible at start up, which is when
most time is taken for actually parsing JSON. I could potentially be
missing something but profiling didn't point to any discernable
difference.
This commit is contained in:
Rapptz 2021-07-05 04:01:19 -04:00
parent e0a9365d61
commit 88d825a803
4 changed files with 27 additions and 6 deletions

View File

@ -25,7 +25,6 @@ DEALINGS IN THE SOFTWARE.
import asyncio import asyncio
from collections import namedtuple, deque from collections import namedtuple, deque
import concurrent.futures import concurrent.futures
import json
import logging import logging
import struct import struct
import sys import sys
@ -421,7 +420,7 @@ class DiscordWebSocket:
msg = self._zlib.decompress(self._buffer) msg = self._zlib.decompress(self._buffer)
msg = msg.decode('utf-8') msg = msg.decode('utf-8')
self._buffer = bytearray() self._buffer = bytearray()
msg = json.loads(msg) msg = utils.from_json(msg)
log.debug('For Shard ID %s: WebSocket Event: %s', self.shard_id, msg) log.debug('For Shard ID %s: WebSocket Event: %s', self.shard_id, msg)
self._dispatch('socket_response', msg) self._dispatch('socket_response', msg)
@ -882,7 +881,7 @@ class DiscordVoiceWebSocket:
# This exception is handled up the chain # This exception is handled up the chain
msg = await asyncio.wait_for(self.ws.receive(), timeout=30.0) msg = await asyncio.wait_for(self.ws.receive(), timeout=30.0)
if msg.type is aiohttp.WSMsgType.TEXT: if msg.type is aiohttp.WSMsgType.TEXT:
await self.received_message(json.loads(msg.data)) await self.received_message(utils.from_json(msg.data))
elif msg.type is aiohttp.WSMsgType.ERROR: elif msg.type is aiohttp.WSMsgType.ERROR:
log.debug('Received %s', msg) log.debug('Received %s', msg)
raise ConnectionClosed(self.ws, shard_id=None) from msg.data raise ConnectionClosed(self.ws, shard_id=None) from msg.data

View File

@ -99,7 +99,7 @@ async def json_or_text(response: aiohttp.ClientResponse) -> Union[Dict[str, Any]
text = await response.text(encoding='utf-8') text = await response.text(encoding='utf-8')
try: try:
if response.headers['content-type'] == 'application/json': if response.headers['content-type'] == 'application/json':
return json.loads(text) return utils.from_json(text)
except KeyError: except KeyError:
# Thanks Cloudflare # Thanks Cloudflare
pass pass

View File

@ -63,6 +63,14 @@ import warnings
from .errors import InvalidArgument from .errors import InvalidArgument
try:
import orjson
except ModuleNotFoundError:
HAS_ORJSON = False
else:
HAS_ORJSON = True
__all__ = ( __all__ = (
'oauth_url', 'oauth_url',
'snowflake_time', 'snowflake_time',
@ -468,8 +476,19 @@ def _bytes_to_base64_data(data: bytes) -> str:
return fmt.format(mime=mime, data=b64) return fmt.format(mime=mime, data=b64)
def to_json(obj: Any) -> str: if HAS_ORJSON:
return json.dumps(obj, separators=(',', ':'), ensure_ascii=True)
def to_json(obj: Any) -> str: # type: ignore
return orjson.dumps(obj).decode('utf-8')
from_json = orjson.loads # type: ignore
else:
def to_json(obj: Any) -> str:
return json.dumps(obj, separators=(',', ':'), ensure_ascii=True)
from_json = json.loads
def _parse_ratelimit_header(request: Any, *, use_clock: bool = False) -> float: def _parse_ratelimit_header(request: Any, *, use_clock: bool = False) -> float:

View File

@ -39,6 +39,9 @@ extras_require = {
'sphinx==4.0.2', 'sphinx==4.0.2',
'sphinxcontrib_trio==1.1.2', 'sphinxcontrib_trio==1.1.2',
'sphinxcontrib-websupport', 'sphinxcontrib-websupport',
],
'speed': [
'orjson>=3.5.4',
] ]
} }