Rev 9: Primitive cache-dropping suppport. in http://people.ubuntu.com/~robertc/baz2.0/plugins/piss/trunk

Robert Collins robertc at robertcollins.net
Mon Aug 20 00:05:54 BST 2007


At http://people.ubuntu.com/~robertc/baz2.0/plugins/piss/trunk

------------------------------------------------------------
revno: 9
revision-id: robertc at robertcollins.net-20070819230532-4b7fx3lt7ir2hsy8
parent: robertc at robertcollins.net-20070819065225-vw68031u3xpbgdqm
committer: Robert Collins <robertc at robertcollins.net>
branch nick: trunk
timestamp: Mon 2007-08-20 09:05:32 +1000
message:
  Primitive cache-dropping suppport.
modified:
  README                         readme-20070501062416-23ztx65da4ul4oxv-2
  benchmarks/__init__.py         __init__.py-20070501062416-23ztx65da4ul4oxv-6
  benchmarks/bench_import.py     bench_import.py-20070501062416-23ztx65da4ul4oxv-7
=== modified file 'README'
--- a/README	2007-05-01 09:00:31 +0000
+++ b/README	2007-08-19 23:05:32 +0000
@@ -17,3 +17,47 @@
 scaling with multiple variables. Eventually we probably want to do statistical
 analysis of the results, but the existing benchmark logic may be enough for
 that.
+
+
+Installation
+------------
+
+To install the plugin you need to install it as a bzr plugin and optionally
+create a small shell script to drop disk caches on your platform, if that is
+possible.
+
+For per user installs:
+ 1. Symlink the plugin directory to ~/.bazaar/plugins/dbus.
+ 2. Create the drop-caches program in your path somewhere. (See below)
+For system wide installs:
+ 1. Run setup.py install with whatever options make sense on your platform.
+ 2. Create the drop-caches program somewhere that is in the path for all your
+    users.
+
+The drop-caches program
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The drop-caches program is a small helper to allow purging the disk cache, to
+(somewhat) test cold-cache scenarios. Its contents for a Linux machine are::
+
+    #!/bin/sh
+    # get written data to disk (not that its guaranteed)
+    sync
+    # (drop the unmodified pages)
+    echo 1 | sudo tee /proc/sys/vm/drop_caches
+
+If your machine does not have this feature, either have a script that will exit
+non-zero, or have no script at all.
+
+And a sudoers rule to allow the privileged operations. I use the following::
+
+    Cmnd_Alias DROPCACHE = /usr/bin/tee /proc/sys/vm/drop_caches
+    ...
+    # Nopasswd entries (last thing in the file).
+    robertc ALL=NOPASSWD: DROPCACHE
+
+
+What next?
+----------
+
+Use ``bzr selftest --benchmark piss`` to run the benchmarks.

=== modified file 'benchmarks/__init__.py'
--- a/benchmarks/__init__.py	2007-08-19 06:52:25 +0000
+++ b/benchmarks/__init__.py	2007-08-19 23:05:32 +0000
@@ -34,22 +34,48 @@
     loader = TestLoader()
     applier = TestScenarioApplier()
     applier.scenarios = []
-    # manual generation of scenarios:
+    # generation of scenarios:
     # decoration
-    for decorated in (False, True):
-        for functions in (0, 10, 100, 1000, 10000):
-            for including_compile in (False, True):
-                scenario_name_bits = []
-                scenario = {}
-                if decorated:
-                    scenario_name_bits.append('decorated')
-                scenario['decorated'] = decorated
-                scenario_name_bits.append('%d functions' % functions)
-                scenario['functions'] = functions
-                if not including_compile:
-                    scenario_name_bits.append('pre-compiled')
-                scenario['compile'] = including_compile
-                applier.scenarios.append((','.join(scenario_name_bits), scenario))
+
+    def decorated(flat_scenarios):
+        for title_elements, scenario_tuples in flat_scenarios:
+            yield (title_elements,
+                   scenario_tuples + [('decorated', False)])
+            yield (title_elements + ['decorated'],
+                   scenario_tuples + [('decorated', True)])
+
+    def function_count(flat_scenarios):
+        for title_elements, scenario_tuples in flat_scenarios:
+            for functions in (0, 10, 100, 1000, 10000):
+                yield (title_elements + ['%d functions' % functions],
+                       scenario_tuples + [('functions', functions)])
+
+    def precompilation(flat_scenarios):
+        for title_elements, scenario_tuples in flat_scenarios:
+            yield (title_elements + ['pre-compiled'],
+                   scenario_tuples + [('compile', False)])
+            yield (title_elements,
+                   scenario_tuples + [('compile', True)])
+
+    def drop_cache(flat_scenarios):
+        # XXX: probe for drop-cache and don't parameterise if its missing.
+        for title_elements, scenario_tuples in flat_scenarios:
+            yield (title_elements,
+                   scenario_tuples + [('drop_cache', False)])
+            yield (title_elements + ['cold cache'],
+                   scenario_tuples + [('drop_cache', True)])
+
+    # what parameters are we applying?
+    parameterisers = [drop_cache, precompilation, function_count, decorated]
+    empty_scenario = [], []
+    flat_scenarios = [empty_scenario]
+    for parameteriser in parameterisers:
+        flat_scenarios = parameteriser(flat_scenarios)
+    for title_elements, scenario_tuples in flat_scenarios:
+        title = ','.join(title_elements)
+        scenario = dict(scenario_tuples)
+        applier.scenarios.append((title, scenario))
+
     result = TestSuite()
     adapt_modules(module_names, applier, loader, result)
     return result

=== modified file 'benchmarks/bench_import.py'
--- a/benchmarks/bench_import.py	2007-08-19 06:52:25 +0000
+++ b/benchmarks/bench_import.py	2007-08-19 23:05:32 +0000
@@ -19,6 +19,7 @@
 """Benchmarks of various python import times."""
 
 import os
+import subprocess
 import sys
 
 from bzrlib.plugins.piss import creator as _mod_creator
@@ -32,18 +33,26 @@
         self.creator = _mod_creator.Creator()
 
     def time_importing_module(self, num_functions, decorated=False,
-            compile=False):
+            compile=False, drop_cache=False):
         self.add_cwd_to_path()
         self.creator.build_module('tiny_piss', num_functions=num_functions,
             decorated=decorated)
         if not compile:
             # import once to generate a .pyc - the common case.
             self.import_and_forget('tiny_piss')
+        if drop_cache:
+            # XXX: Handle missing drop-caches, and also non-zero exit codes.
+            result = subprocess.call('drop-caches', stdin=subprocess.PIPE,
+                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         self.time(self.import_and_forget, 'tiny_piss')
 
-    def test_import_parameterised(self):
+    def test_import(self):
+        # XXX: We currently require all parameters to be set, what might be
+        # nice is to have helper methods for all the parameters that default
+        # to a safe setting, so we can selectively parameterise as the
+        # parameter space grows.
         self.time_importing_module(self.functions, decorated=self.decorated,
-            compile=self.compile)
+            compile=self.compile, drop_cache=self.drop_cache)
 
     def add_cwd_to_path(self):
         sys.path.append(os.getcwd())



More information about the bazaar-commits mailing list