Browse Source

Improve performance of value -> enum by about 5x.

pull/2092/head
Rapptz 6 years ago
parent
commit
6f26a4aad8
  1. 2
      discord/audit_logs.py
  2. 57
      discord/enums.py
  3. 2
      discord/user.py

2
discord/audit_logs.py

@ -216,7 +216,7 @@ class AuditLogEntry:
self._from_data(data)
def _from_data(self, data):
self.action = enums.AuditLogAction(data['action_type'])
self.action = enums.try_enum(enums.AuditLogAction, data['action_type'])
self.id = int(data['id'])
# this key is technically not usually present

57
discord/enums.py

@ -32,6 +32,20 @@ __all__ = ['ChannelType', 'MessageType', 'VoiceRegion', 'SpeakingState',
'UserFlags', 'ActivityType', 'HypeSquadHouse', 'NotificationLevel',
'PremiumType', 'UserContentFilter', 'FriendFlags', 'Theme']
def fast_lookup(cls):
# NOTE: implies hashable
try:
lookup = cls._value2member_map_
except AttributeError:
lookup = {
member.value: member
for member in cls.__members__
}
finally:
cls.__fast_value_lookup__ = lookup
return cls
@fast_lookup
class ChannelType(Enum):
text = 0
private = 1
@ -44,6 +58,7 @@ class ChannelType(Enum):
def __str__(self):
return self.name
@fast_lookup
class MessageType(Enum):
default = 0
recipient_add = 1
@ -54,6 +69,7 @@ class MessageType(Enum):
pins_add = 6
new_member = 7
@fast_lookup
class VoiceRegion(Enum):
us_west = 'us-west'
us_east = 'us-east'
@ -78,6 +94,7 @@ class VoiceRegion(Enum):
def __str__(self):
return self.value
@fast_lookup
class SpeakingState(Enum):
none = 0
voice = 1
@ -90,6 +107,7 @@ class SpeakingState(Enum):
def __int__(self):
return self.value
@fast_lookup
class VerificationLevel(Enum):
none = 0
low = 1
@ -102,6 +120,7 @@ class VerificationLevel(Enum):
def __str__(self):
return self.name
@fast_lookup
class ContentFilter(Enum):
disabled = 0
no_role = 1
@ -110,11 +129,13 @@ class ContentFilter(Enum):
def __str__(self):
return self.name
@fast_lookup
class UserContentFilter(Enum):
disabled = 0
friends = 1
all_messages = 2
@fast_lookup
class FriendFlags(Enum):
noone = 0
mutual_guilds = 1
@ -122,10 +143,12 @@ class FriendFlags(Enum):
guild_and_friends = 3
everyone = 4
@fast_lookup
class Theme(Enum):
light = 'light'
dark = 'dark'
@fast_lookup
class Status(Enum):
online = 'online'
offline = 'offline'
@ -137,6 +160,7 @@ class Status(Enum):
def __str__(self):
return self.value
@fast_lookup
class DefaultAvatar(Enum):
blurple = 0
grey = 1
@ -148,21 +172,25 @@ class DefaultAvatar(Enum):
def __str__(self):
return self.name
@fast_lookup
class RelationshipType(Enum):
friend = 1
blocked = 2
incoming_request = 3
outgoing_request = 4
@fast_lookup
class NotificationLevel(Enum):
all_messages = 0
only_mentions = 1
@fast_lookup
class AuditLogActionCategory(Enum):
create = 1
delete = 2
update = 3
@fast_lookup
class AuditLogAction(Enum):
guild_update = 1
channel_create = 10
@ -245,6 +273,7 @@ class AuditLogAction(Enum):
elif v < 80:
return 'message'
@fast_lookup
class UserFlags(Enum):
staff = 1
partner = 2
@ -255,6 +284,7 @@ class UserFlags(Enum):
hypesquad_balance = 256
early_supporter = 512
@fast_lookup
class ActivityType(Enum):
unknown = -1
playing = 0
@ -262,11 +292,13 @@ class ActivityType(Enum):
listening = 2
watching = 3
@fast_lookup
class HypeSquadHouse(Enum):
bravery = 1
brilliance = 2
balance = 3
@fast_lookup
class PremiumType(Enum):
nitro_classic = 1
nitro = 2
@ -276,7 +308,28 @@ def try_enum(cls, val):
If it fails it returns the value instead.
"""
# For some ungodly reason, `cls(x)` is *really* slow
# For most use cases it's about 750ns per call
# Internally this is dispatched like follows:
# cls(x)
# cls.__new__(cls, x)
# cls._value2member_map[x]
# if above fails ^
# find it in cls._member_map.items()
# Accessing the _value2member_map directly gives the biggest
# boost to performance, from 750ns to 130ns
# Now, the weird thing is that regular dict access is approx 31ns
# So there's a slowdown in the attribute access somewhere in the
# __getattr__ chain that I can't do much about
# Since this relies on internals the enums have an internal shim
# decorator that defines an alias for my own purposes or creates
# it for me under __fast_value_lookup__
try:
return cls(val)
except ValueError:
return cls.__fast_value_lookup__[val]
except (KeyError, AttributeError):
return val

2
discord/user.py

@ -164,7 +164,7 @@ class BaseUser(_BaseUser):
@property
def default_avatar(self):
"""Returns the default avatar for a given user. This is calculated by the user's discriminator"""
return DefaultAvatar(int(self.discriminator) % len(DefaultAvatar))
return try_enum(DefaultAvatar, int(self.discriminator) % len(DefaultAvatar))
@property
def default_avatar_url(self):

Loading…
Cancel
Save