Various speed optimizations in various places, following further profiling.
This commit is contained in:
parent
83fa9397d5
commit
4c83d3e7a1
7 changed files with 75 additions and 59 deletions
|
|
@ -142,7 +142,8 @@ def get_and_merge_cmdsets(caller):
|
||||||
# report cmdset errors to user (these should already have been logged)
|
# report cmdset errors to user (these should already have been logged)
|
||||||
yield [caller.msg(cmdset.message) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR"]
|
yield [caller.msg(cmdset.message) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR"]
|
||||||
# sort cmdsets after reverse priority (highest prio are merged in last)
|
# sort cmdsets after reverse priority (highest prio are merged in last)
|
||||||
cmdsets = yield sorted(cmdsets, key=lambda x: x.priority)
|
yield cmdsets.sort(key=lambda x: x.priority)
|
||||||
|
#cmdsets = yield sorted(cmdsets, key=lambda x: x.priority)
|
||||||
|
|
||||||
if cmdsets:
|
if cmdsets:
|
||||||
# Merge all command sets into one, beginning with the lowest-prio one
|
# Merge all command sets into one, beginning with the lowest-prio one
|
||||||
|
|
|
||||||
|
|
@ -144,10 +144,12 @@ class CmdSet(object):
|
||||||
if key:
|
if key:
|
||||||
self.key = key
|
self.key = key
|
||||||
self.commands = []
|
self.commands = []
|
||||||
|
self.system_commands = []
|
||||||
self.actual_mergetype = self.mergetype
|
self.actual_mergetype = self.mergetype
|
||||||
self.cmdsetobj = cmdsetobj
|
self.cmdsetobj = cmdsetobj
|
||||||
# initialize system
|
# initialize system
|
||||||
self.at_cmdset_creation()
|
self.at_cmdset_creation()
|
||||||
|
self._contains_cache = {}
|
||||||
|
|
||||||
# Priority-sensitive merge operations for cmdsets
|
# Priority-sensitive merge operations for cmdsets
|
||||||
|
|
||||||
|
|
@ -223,7 +225,13 @@ class CmdSet(object):
|
||||||
Returns True if this cmdset contains the given command (as defined
|
Returns True if this cmdset contains the given command (as defined
|
||||||
by command name and aliases). This allows for things like 'if cmd in cmdset'
|
by command name and aliases). This allows for things like 'if cmd in cmdset'
|
||||||
"""
|
"""
|
||||||
return othercmd in self.commands
|
# optimization test
|
||||||
|
try:
|
||||||
|
return self._contains_cache[othercmd]
|
||||||
|
except KeyError:
|
||||||
|
ret = othercmd in self.commands
|
||||||
|
self._contains_cache[othercmd] = ret
|
||||||
|
return ret
|
||||||
|
|
||||||
def __add__(self, cmdset_b):
|
def __add__(self, cmdset_b):
|
||||||
"""
|
"""
|
||||||
|
|
@ -327,18 +335,29 @@ class CmdSet(object):
|
||||||
cmds = [self._instantiate(c) for c in cmd]
|
cmds = [self._instantiate(c) for c in cmd]
|
||||||
else:
|
else:
|
||||||
cmds = [self._instantiate(cmd)]
|
cmds = [self._instantiate(cmd)]
|
||||||
|
commands = self.commands
|
||||||
|
system_commands = self.system_commands
|
||||||
for cmd in cmds:
|
for cmd in cmds:
|
||||||
# add all commands
|
# add all commands
|
||||||
if not hasattr(cmd, 'obj'):
|
if not hasattr(cmd, 'obj'):
|
||||||
cmd.obj = self.cmdsetobj
|
cmd.obj = self.cmdsetobj
|
||||||
try:
|
try:
|
||||||
ic = self.commands.index(cmd)
|
ic = commands.index(cmd)
|
||||||
self.commands[ic] = cmd # replace
|
commands[ic] = cmd # replace
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.commands.append(cmd)
|
commands.append(cmd)
|
||||||
# extra run to make sure to avoid doublets
|
# extra run to make sure to avoid doublets
|
||||||
self.commands = list(set(self.commands))
|
self.commands = list(set(commands))
|
||||||
#print "In cmdset.add(cmd):", self.key, cmd
|
#print "In cmdset.add(cmd):", self.key, cmd
|
||||||
|
# add system_command to separate list as well,
|
||||||
|
# for quick look-up
|
||||||
|
if cmd.key.startswith("__"):
|
||||||
|
try:
|
||||||
|
ic = system_commands.index(cmd)
|
||||||
|
system_commands[ic] = cmd # replace
|
||||||
|
except ValueError:
|
||||||
|
system_commands.append(cmd)
|
||||||
|
|
||||||
|
|
||||||
def remove(self, cmd):
|
def remove(self, cmd):
|
||||||
"""
|
"""
|
||||||
|
|
@ -369,7 +388,8 @@ class CmdSet(object):
|
||||||
commands starting with double underscore __.
|
commands starting with double underscore __.
|
||||||
These are excempt from merge operations.
|
These are excempt from merge operations.
|
||||||
"""
|
"""
|
||||||
return [cmd for cmd in self.commands if cmd.key.startswith('__')]
|
return self.system_commands
|
||||||
|
#return [cmd for cmd in self.commands if cmd.key.startswith('__')]
|
||||||
|
|
||||||
def make_unique(self, caller):
|
def make_unique(self, caller):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ class CommandMeta(type):
|
||||||
mcs.aliases = [str(alias).strip().lower() for alias in mcs.aliases]
|
mcs.aliases = [str(alias).strip().lower() for alias in mcs.aliases]
|
||||||
# optimization - a set is much faster to match against than a list
|
# optimization - a set is much faster to match against than a list
|
||||||
mcs._matchset = set([mcs.key] + mcs.aliases)
|
mcs._matchset = set([mcs.key] + mcs.aliases)
|
||||||
# optimization for retrieving aliases and key as one list
|
# optimization for looping over keys+aliases
|
||||||
mcs._keyaliases = [mcs.key] + mcs.aliases
|
mcs._keyaliases = tuple(mcs._matchset)
|
||||||
|
|
||||||
# by default we don't save the command between runs
|
# by default we don't save the command between runs
|
||||||
if not hasattr(mcs, "save_for_next"):
|
if not hasattr(mcs, "save_for_next"):
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ _ME = _("me")
|
||||||
_SELF = _("self")
|
_SELF = _("self")
|
||||||
_HERE = _("here")
|
_HERE = _("here")
|
||||||
|
|
||||||
|
|
||||||
def clean_content_cache(obj):
|
def clean_content_cache(obj):
|
||||||
"Clean obj's content cache"
|
"Clean obj's content cache"
|
||||||
_SA(obj, "_contents_cache", None)
|
_SA(obj, "_contents_cache", None)
|
||||||
|
|
@ -428,8 +427,8 @@ class ObjectDB(TypedObject):
|
||||||
Retrieve sessions connected to this object.
|
Retrieve sessions connected to this object.
|
||||||
"""
|
"""
|
||||||
# if the player is not connected, this will simply be an empty list.
|
# if the player is not connected, this will simply be an empty list.
|
||||||
if self.player:
|
if _GA(self, "player"):
|
||||||
return self.player.sessions
|
return _GA(_GA(self, "player"), "sessions")
|
||||||
return []
|
return []
|
||||||
sessions = property(__sessions_get)
|
sessions = property(__sessions_get)
|
||||||
|
|
||||||
|
|
@ -439,14 +438,15 @@ class ObjectDB(TypedObject):
|
||||||
Convenience function for checking if an active player is
|
Convenience function for checking if an active player is
|
||||||
currently connected to this object
|
currently connected to this object
|
||||||
"""
|
"""
|
||||||
return any(self.sessions)
|
return any(_GA(self, "sessions"))
|
||||||
has_player = property(__has_player_get)
|
has_player = property(__has_player_get)
|
||||||
is_player = property(__has_player_get)
|
is_player = property(__has_player_get)
|
||||||
|
|
||||||
#@property
|
#@property
|
||||||
def __is_superuser_get(self):
|
def __is_superuser_get(self):
|
||||||
"Check if user has a player, and if so, if it is a superuser."
|
"Check if user has a player, and if so, if it is a superuser."
|
||||||
return any(self.sessions) and self.player.is_superuser
|
#return any(self.sessions) and self.player.is_superuser
|
||||||
|
return any(_GA(self, "sessions")) and _GA(_GA(self, "player"), "is_superuser")
|
||||||
is_superuser = property(__is_superuser_get)
|
is_superuser = property(__is_superuser_get)
|
||||||
|
|
||||||
# contents
|
# contents
|
||||||
|
|
|
||||||
|
|
@ -637,31 +637,26 @@ class Object(TypeClass):
|
||||||
"""
|
"""
|
||||||
if not pobject:
|
if not pobject:
|
||||||
return
|
return
|
||||||
string = "{c%s{n" % self.name
|
# get and identify all objects
|
||||||
desc = self.attr("desc")
|
visible = (con for con in self.contents if con != pobject and con.access(pobject, "view"))
|
||||||
|
exits, users, things = [], [], []
|
||||||
|
for con in visible:
|
||||||
|
key = con.key
|
||||||
|
if con.destination:
|
||||||
|
exits.append(key)
|
||||||
|
elif con.has_player:
|
||||||
|
users.append("{c%s{n" % key)
|
||||||
|
else:
|
||||||
|
things.append(key)
|
||||||
|
# get description, build string
|
||||||
|
string = "{c%s{n" % self.key
|
||||||
|
desc = self.db.desc
|
||||||
if desc:
|
if desc:
|
||||||
string += "\n %s" % desc
|
string += "\n %s" % desc
|
||||||
exits = []
|
|
||||||
users = []
|
|
||||||
things = []
|
|
||||||
for content in [con for con in self.contents if con.access(pobject, 'view')]:
|
|
||||||
if content == pobject:
|
|
||||||
continue
|
|
||||||
name = content.name
|
|
||||||
if content.destination:
|
|
||||||
exits.append(name)
|
|
||||||
elif content.has_player:
|
|
||||||
users.append(name)
|
|
||||||
else:
|
|
||||||
things.append(name)
|
|
||||||
if exits:
|
if exits:
|
||||||
string += "\n{wExits:{n " + ", ".join(exits)
|
string += "\n{wExits:{n " + ", ".join(exits)
|
||||||
if users or things:
|
if users or things:
|
||||||
string += "\n{wYou see: {n"
|
string += "\n{wYou see:{n " + ", ".join(users + things)
|
||||||
if users:
|
|
||||||
string += "{c" + ", ".join(users) + "{n "
|
|
||||||
if things:
|
|
||||||
string += ", ".join(things)
|
|
||||||
return string
|
return string
|
||||||
|
|
||||||
def at_desc(self, looker=None):
|
def at_desc(self, looker=None):
|
||||||
|
|
|
||||||
|
|
@ -180,9 +180,9 @@ class PlayerDB(TypedObject):
|
||||||
"Parent must be initiated first"
|
"Parent must be initiated first"
|
||||||
TypedObject.__init__(self, *args, **kwargs)
|
TypedObject.__init__(self, *args, **kwargs)
|
||||||
# handlers
|
# handlers
|
||||||
self.cmdset = CmdSetHandler(self)
|
_SA(self, "cmdset", CmdSetHandler(self))
|
||||||
self.cmdset.update(init_mode=True)
|
_GA(self, "cmdset").update(init_mode=True)
|
||||||
self.nicks = PlayerNickHandler(self)
|
_SA(self, "nicks", PlayerNickHandler(self))
|
||||||
|
|
||||||
# Wrapper properties to easily set database fields. These are
|
# Wrapper properties to easily set database fields. These are
|
||||||
# @property decorators that allows to access these fields using
|
# @property decorators that allows to access these fields using
|
||||||
|
|
@ -240,21 +240,21 @@ class PlayerDB(TypedObject):
|
||||||
#@property
|
#@property
|
||||||
def cmdset_storage_get(self):
|
def cmdset_storage_get(self):
|
||||||
"Getter. Allows for value = self.name. Returns a list of cmdset_storage."
|
"Getter. Allows for value = self.name. Returns a list of cmdset_storage."
|
||||||
if self.db_cmdset_storage:
|
if _GA(self, "db_cmdset_storage"):
|
||||||
return [path.strip() for path in self.db_cmdset_storage.split(',')]
|
return [path.strip() for path in _GA(self, "db_cmdset_storage").split(',')]
|
||||||
return []
|
return []
|
||||||
#@cmdset_storage.setter
|
#@cmdset_storage.setter
|
||||||
def cmdset_storage_set(self, value):
|
def cmdset_storage_set(self, value):
|
||||||
"Setter. Allows for self.name = value. Stores as a comma-separated string."
|
"Setter. Allows for self.name = value. Stores as a comma-separated string."
|
||||||
if utils.is_iter(value):
|
if utils.is_iter(value):
|
||||||
value = ",".join([str(val).strip() for val in value])
|
value = ",".join([str(val).strip() for val in value])
|
||||||
self.db_cmdset_storage = value
|
_SA(self, "db_cmdset_storage", value)
|
||||||
self.save()
|
_GA(self, "save")()
|
||||||
#@cmdset_storage.deleter
|
#@cmdset_storage.deleter
|
||||||
def cmdset_storage_del(self):
|
def cmdset_storage_del(self):
|
||||||
"Deleter. Allows for del self.name"
|
"Deleter. Allows for del self.name"
|
||||||
self.db_cmdset_storage = ""
|
_SA(self, "db_cmdset_storage", "")
|
||||||
self.save()
|
_GA(self, "save")()
|
||||||
cmdset_storage = property(cmdset_storage_get, cmdset_storage_set, cmdset_storage_del)
|
cmdset_storage = property(cmdset_storage_get, cmdset_storage_set, cmdset_storage_del)
|
||||||
|
|
||||||
#@property
|
#@property
|
||||||
|
|
@ -281,10 +281,10 @@ class PlayerDB(TypedObject):
|
||||||
#
|
#
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return smart_str("%s(player %s)" % (self.name, self.dbid))
|
return smart_str("%s(player %s)" % (_GA(self, "name"), _GA(self, "dbid")))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"%s(player#%s)" % (self.name, self.dbid)
|
return u"%s(player#%s)" % (_GA(self, "name"), _GA(self, "dbid"))
|
||||||
|
|
||||||
# this is required to properly handle attributes and typeclass loading
|
# this is required to properly handle attributes and typeclass loading
|
||||||
_typeclass_paths = settings.PLAYER_TYPECLASS_PATHS
|
_typeclass_paths = settings.PLAYER_TYPECLASS_PATHS
|
||||||
|
|
@ -297,15 +297,15 @@ class PlayerDB(TypedObject):
|
||||||
#@property
|
#@property
|
||||||
def name_get(self):
|
def name_get(self):
|
||||||
"Getter. Allows for value = self.name"
|
"Getter. Allows for value = self.name"
|
||||||
if not self._name_cache:
|
if not _GA(self, "_name_cache"):
|
||||||
self._name_cache = self.user.username
|
_SA(self, "_name_cache", _GA(self,"user").username)
|
||||||
return self._name_cache
|
return _GA(self, "_name_cache")
|
||||||
#@name.setter
|
#@name.setter
|
||||||
def name_set(self, value):
|
def name_set(self, value):
|
||||||
"Setter. Allows for player.name = newname"
|
"Setter. Allows for player.name = newname"
|
||||||
self.user.username = value
|
_GA(self, "user").username = value
|
||||||
self.user.save() # this might be stopped by Django?
|
_GA(self, "user").save()
|
||||||
self._name_cache = value
|
_SA(self, "_name_cache", value)
|
||||||
#@name.deleter
|
#@name.deleter
|
||||||
def name_del(self):
|
def name_del(self):
|
||||||
"Deleter. Allows for del self.name"
|
"Deleter. Allows for del self.name"
|
||||||
|
|
@ -317,9 +317,9 @@ class PlayerDB(TypedObject):
|
||||||
#@property
|
#@property
|
||||||
def uid_get(self):
|
def uid_get(self):
|
||||||
"Getter. Retrieves the user id"
|
"Getter. Retrieves the user id"
|
||||||
if not self._uid_cache:
|
if not _GA(self, "_uid_cache"):
|
||||||
self._uid_cache = self.user.id
|
_SA(self, "_uid_cache", _GA(self, "user").id)
|
||||||
return self._uid_cache
|
return _GA(self, "_uid_cache")
|
||||||
def uid_set(self, value):
|
def uid_set(self, value):
|
||||||
raise Exception("User id cannot be set!")
|
raise Exception("User id cannot be set!")
|
||||||
def uid_del(self):
|
def uid_del(self):
|
||||||
|
|
@ -345,9 +345,9 @@ class PlayerDB(TypedObject):
|
||||||
_is_superuser_cache = None
|
_is_superuser_cache = None
|
||||||
def is_superuser_get(self):
|
def is_superuser_get(self):
|
||||||
"Superusers have all permissions."
|
"Superusers have all permissions."
|
||||||
if self._is_superuser_cache == None:
|
if _GA(self, "_is_superuser_cache") == None:
|
||||||
self._is_superuser_cache = self.user.is_superuser
|
_SA(self, "_is_superuser_cache", _GA(self, "user").is_superuser)
|
||||||
return self._is_superuser_cache
|
return _GA(self, "_is_superuser_cache")
|
||||||
is_superuser = property(is_superuser_get)
|
is_superuser = property(is_superuser_get)
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
@ -379,7 +379,7 @@ class PlayerDB(TypedObject):
|
||||||
"""
|
"""
|
||||||
Swaps character, if possible
|
Swaps character, if possible
|
||||||
"""
|
"""
|
||||||
return self.__class__.objects.swap_character(self, new_character, delete_old_character=delete_old_character)
|
return _GA(self, "__class__").objects.swap_character(self, new_character, delete_old_character=delete_old_character)
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
"Make sure to delete user also when deleting player - the two may never exist separately."
|
"Make sure to delete user also when deleting player - the two may never exist separately."
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ DEFAULT_NCLIENTS = 1
|
||||||
# time between each 'tick', in seconds, if not set on command
|
# time between each 'tick', in seconds, if not set on command
|
||||||
# line. All launched clients will be called upon to possibly do an
|
# line. All launched clients will be called upon to possibly do an
|
||||||
# action with this frequency.
|
# action with this frequency.
|
||||||
DEFAULT_TIMESTEP = 5
|
DEFAULT_TIMESTEP = 2
|
||||||
# Port to use, if not specified on command line
|
# Port to use, if not specified on command line
|
||||||
DEFAULT_PORT = settings.TELNET_PORTS[0]
|
DEFAULT_PORT = settings.TELNET_PORTS[0]
|
||||||
# chance of an action happening, per timestep. This helps to
|
# chance of an action happening, per timestep. This helps to
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue