Commit c8410ed6 authored by Guido van Rossum's avatar Guido van Rossum

Refactored the classes, moving more infrastructure into the Simulation

base class.
parent 5cfea0a2
...@@ -80,52 +80,33 @@ def main(): ...@@ -80,52 +80,33 @@ def main():
class Simulation: 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): def __init__(self):
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
# Initialize global statistics # Initialize global statistics
self.epoch = None self.epoch = None
self.total_flips = 0
self.total_loads = 0 self.total_loads = 0
self.total_hits = 0 self.total_hits = 0 # Subclass must increment
self.total_invals = 0 self.total_invals = 0
self.total_writes = 0 self.total_writes = 0
# Reset per-run statistics and simulation data # Reset per-run statistics and set up simulation data
self.restart() self.restart()
def restart(self): def restart(self):
# Set up statistics # Reset per-run statistics
self.flips = 0
self.loads = 0 self.loads = 0
self.hits = 0 self.hits = 0 # Subclass must increment
self.invals = 0 self.invals = 0
self.writes = 0 self.writes = 0
self.ts0 = None 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): def event(self, ts, dlen, _version, code, _current, oid, _serial):
# Record first and last timestamp seen # Record first and last timestamp seen
...@@ -140,45 +121,99 @@ class ZEOCacheSimulation(Simulation): ...@@ -140,45 +121,99 @@ class ZEOCacheSimulation(Simulation):
# unless the object in fact did not exist). Updates always write. # unless the object in fact did not exist). Updates always write.
if dlen and code & 0x70 in (0x20, 0x30, 0x50): if dlen and code & 0x70 in (0x20, 0x30, 0x50):
if code == 0x3A: if code == 0x3A:
# Update
self.writes += 1 self.writes += 1
self.total_writes += 1 self.total_writes += 1
self.write(oid, dlen)
else: else:
# Load hit or store -- these are really the load requests
self.loads += 1 self.loads += 1
self.total_loads += 1 self.total_loads += 1
if code != 0x3A and (self.fileoids[self.current].get(oid) or self.load(oid, dlen)
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
elif code & 0x70 == 0x10: elif code & 0x70 == 0x10:
# Invalidate # Invalidate
if self.fileoids[self.current].get(oid): self.invals += 1
self.invals += 1 self.total_invals += 1
self.total_invals += 1 self.inval(oid)
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]
elif code == 0x00: elif code == 0x00:
# Restart # Restart
self.report() self.report()
self.restart() 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" format = "%12s %9s %8s %8s %6s %6s %5s %6s"
def printheader(self): def printheader(self):
......
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