Browse Source

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.
pull/7190/head
Rapptz 4 years ago
parent
commit
88d825a803
  1. 5
      discord/gateway.py
  2. 2
      discord/http.py
  3. 23
      discord/utils.py
  4. 3
      setup.py

5
discord/gateway.py

@ -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

2
discord/http.py

@ -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

23
discord/utils.py

@ -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:

3
setup.py

@ -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',
] ]
} }

Loading…
Cancel
Save