Commit 228604dd authored by Jason Madden's avatar Jason Madden

Connection.setstate passes the object's OID as a parameter to the helper Connection._setstate.

This is a performance optimization for PyPy (profiling shows many recursive calls to Persistent.__getattribute__, and recursive calls seem to trouble the PyPy JIT; this eliminates many of them when loading objects):

"Transaction",                 AFTER       BEFORE
"Add 3000 Objects",             20205      18505
"Update 3000 Objects",          24191      18807
"Read 3000 Warm Objects",       28920      26671
"Read 3000 Cold Objects",       28745      27487
"Read 3000 Hot Objects",        29563      27487
"Read 3000 Steamin' Objects", 1033758     916587
parent 8840c09a
......@@ -866,7 +866,7 @@ class Connection(ExportImport, object):
raise
try:
self._setstate(obj)
self._setstate(obj, oid)
except ConflictError:
raise
except:
......@@ -874,8 +874,11 @@ class Connection(ExportImport, object):
className(obj), oid_repr(oid))
raise
def _setstate(self, obj):
def _setstate(self, obj, oid):
# Helper for setstate(), which provides logging of failures.
# We accept the oid param, which must be the same as obj._p_oid,
# as a performance optimization for the pure-Python persistent implementation
# where accessing an attribute involves __getattribute__ calls
# The control flow is complicated here to avoid loading an
# object revision that we are sure we aren't going to use. As
......@@ -890,7 +893,7 @@ class Connection(ExportImport, object):
if self.before is not None:
# Load data that was current before the time we have.
before = self.before
t = self._storage.loadBefore(obj._p_oid, before)
t = self._storage.loadBefore(oid, before)
if t is None:
raise POSKeyError() # historical connection!
p, serial, end = t
......@@ -903,16 +906,16 @@ class Connection(ExportImport, object):
if self._invalidatedCache:
raise ReadConflictError()
if (obj._p_oid in self._invalidated):
if (oid in self._invalidated):
self._load_before_or_conflict(obj)
return
p, serial = self._storage.load(obj._p_oid, '')
p, serial = self._storage.load(oid, '')
self._load_count += 1
self._inv_lock.acquire()
try:
invalid = obj._p_oid in self._invalidated
invalid = oid in self._invalidated
finally:
self._inv_lock.release()
......@@ -922,13 +925,13 @@ class Connection(ExportImport, object):
self._reader.setGhostState(obj, p)
obj._p_serial = serial
self._cache.update_object_size_estimation(obj._p_oid, len(p))
self._cache.update_object_size_estimation(oid, len(p))
obj._p_estimated_size = len(p)
# Blob support
if isinstance(obj, Blob):
obj._p_blob_uncommitted = None
obj._p_blob_committed = self._storage.loadBlob(obj._p_oid, serial)
obj._p_blob_committed = self._storage.loadBlob(oid, serial)
def _load_before_or_conflict(self, obj):
"""Load non-current state for obj or raise ReadConflictError."""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment