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():
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,45 +121,99 @@ class ZEOCacheSimulation(Simulation):
# 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"
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