[Zodb-checkins] CVS: ZODB3/ZEO - simul.py:1.4
Guido van Rossum
guido@python.org
Fri, 6 Sep 2002 12:09:10 -0400
Update of /cvs-repository/ZODB3/ZEO
In directory cvs.zope.org:/tmp/cvs-serv5084
Modified Files:
simul.py
Log Message:
Refactored the classes, moving more infrastructure into the Simulation
base class.
=== ZODB3/ZEO/simul.py 1.3 => 1.4 ===
--- ZODB3/ZEO/simul.py:1.3 Fri Sep 6 11:31:01 2002
+++ ZODB3/ZEO/simul.py Fri Sep 6 12:09:10 2002
@@ -80,52 +80,33 @@
class Simulation:
- """Abstract base class to define simulation interface.
+ """Base class for simulations.
- These are the only methods that the driver program calls.
+ The driver program calls: event(), printheader(), finish().
- The constructor signature is not part of the interface.
+ The standard event() method calls these additional methods:
+ write(), load(), inval(), report(), restart(); the standard
+ finish() method also calls report().
"""
- def event(self, ts, dlen, version, code, current, oid, serial):
- pass
-
- def printheader(self):
- pass
-
- def finish(self):
- pass
-
-class ZEOCacheSimulation(Simulation):
-
- """Simulate the current (ZEO 1.0 and 2.0) ZEO cache behavior."""
-
- def __init__(self, cachelimit):
- # Store simulation parameters
- self.filelimit = cachelimit / 2
+ def __init__(self):
# Initialize global statistics
self.epoch = None
- self.total_flips = 0
self.total_loads = 0
- self.total_hits = 0
+ self.total_hits = 0 # Subclass must increment
self.total_invals = 0
self.total_writes = 0
- # Reset per-run statistics and simulation data
+ # Reset per-run statistics and set up simulation data
self.restart()
def restart(self):
- # Set up statistics
- self.flips = 0
+ # Reset per-run statistics
self.loads = 0
- self.hits = 0
+ self.hits = 0 # Subclass must increment
self.invals = 0
self.writes = 0
self.ts0 = None
- # Set up simulation data
- self.filesize = [4, 4] # account for magic number
- self.fileoids = [{}, {}]
- self.current = 0 # index into filesize, fileoids
def event(self, ts, dlen, _version, code, _current, oid, _serial):
# Record first and last timestamp seen
@@ -140,44 +121,98 @@
# unless the object in fact did not exist). Updates always write.
if dlen and code & 0x70 in (0x20, 0x30, 0x50):
if code == 0x3A:
+ # Update
self.writes += 1
self.total_writes += 1
+ self.write(oid, dlen)
else:
+ # Load hit or store -- these are really the load requests
self.loads += 1
self.total_loads += 1
- if code != 0x3A and (self.fileoids[self.current].get(oid) or
- self.fileoids[1 - self.current].get(oid)):
- self.hits += 1
- self.total_hits += 1
- else:
- # Simulate a miss+store. Fudge because dlen is
- # rounded up to multiples of 256. (31 is header
- # overhead per cache record; 127 is to compensate for
- # rounding up to multiples of 256.)
- dlen = dlen + 31 - 127
- if self.filesize[self.current] + dlen > self.filelimit:
- # Cache flip
- self.flips += 1
- self.total_flips += 1
- self.current = 1 - self.current
- self.filesize[self.current] = 4
- self.fileoids[self.current] = {}
- self.filesize[self.current] += dlen
- self.fileoids[self.current][oid] = 1
+ self.load(oid, dlen)
elif code & 0x70 == 0x10:
# Invalidate
- if self.fileoids[self.current].get(oid):
- self.invals += 1
- self.total_invals += 1
- del self.fileoids[self.current][oid]
- elif self.fileoids[1 - self.current].get(oid):
- self.invals += 1
- self.total_invals += 1
- del self.fileoids[1 - self.current][oid]
+ self.invals += 1
+ self.total_invals += 1
+ self.inval(oid)
elif code == 0x00:
# Restart
self.report()
self.restart()
+
+ def printheader(self):
+ pass
+
+ def write(self, oid, size):
+ pass
+
+ def load(self, oid, size):
+ pass
+
+ def inval(self, oid):
+ pass
+
+ def finish(self):
+ self.report()
+
+ def report(self):
+ pass
+
+class ZEOCacheSimulation(Simulation):
+
+ """Simulate the current (ZEO 1.0 and 2.0) ZEO cache behavior.
+
+ This assumes the cache is not persistent (we don't know how to
+ simulate cache validation.)
+
+ """
+
+ def __init__(self, cachelimit):
+ # Initialize base class
+ Simulation.__init__(self)
+ # Store simulation parameters
+ self.filelimit = cachelimit / 2
+ # Initialize additional global statistics
+ self.total_flips = 0
+
+ def restart(self):
+ # Reset base class
+ Simulation.restart(self)
+ # Reset additional per-run statistics
+ self.flips = 0
+ # Set up simulation
+ self.filesize = [4, 4] # account for magic number
+ self.fileoids = [{}, {}]
+ self.current = 0 # index into filesize, fileoids
+
+ def load(self, oid, size):
+ if (self.fileoids[self.current].get(oid) or
+ self.fileoids[1 - self.current].get(oid)):
+ self.hits += 1
+ self.total_hits += 1
+ else:
+ self.write(oid, size)
+
+ def write(self, oid, size):
+ # Fudge because size is rounded up to multiples of 256. (31
+ # is header overhead per cache record; 127 is to compensate
+ # for rounding up to multiples of 256.)
+ size = size + 31 - 127
+ if self.filesize[self.current] + size > self.filelimit:
+ # Cache flip
+ self.flips += 1
+ self.total_flips += 1
+ self.current = 1 - self.current
+ self.filesize[self.current] = 4
+ self.fileoids[self.current] = {}
+ self.filesize[self.current] += size
+ self.fileoids[self.current][oid] = 1
+
+ def inval(self, oid):
+ if self.fileoids[self.current].get(oid):
+ del self.fileoids[self.current][oid]
+ elif self.fileoids[1 - self.current].get(oid):
+ del self.fileoids[1 - self.current][oid]
format = "%12s %9s %8s %8s %6s %6s %5s %6s"