glFinish to complete bench before stopping stopwatch.
authorbungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 18 May 2011 18:37:07 +0000 (18:37 +0000)
committerbungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 18 May 2011 18:37:07 +0000 (18:37 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@1366 2bbb7eff-a529-9590-31e7-b0007b416f81

bench/bench_compare.py [new file with mode: 0644]
bench/benchmain.cpp

diff --git a/bench/bench_compare.py b/bench/bench_compare.py
new file mode 100644 (file)
index 0000000..f6909b1
--- /dev/null
@@ -0,0 +1,140 @@
+'''
+Created on May 16, 2011
+
+@author: bungeman
+'''
+import sys
+import getopt
+import re
+
+def parse(lines):
+    """Takes iterable lines of bench output, returns {bench:{config:time}}."""
+    
+    benches = {}
+    current_bench = None
+    
+    for line in lines:
+        #see if this line starts a new bench
+        new_bench = re.search('running bench \[\d+ \d+\] (.{28})', line)
+        if new_bench:
+            current_bench = new_bench.group(1)
+        
+        #add configs on this line to the current bench
+        if current_bench:
+            for new_config in re.finditer('  (.{4}): msecs = (\d+\.\d+)', line):
+                current_config = new_config.group(1)
+                current_time = float(new_config.group(2))
+                if current_bench in benches:
+                    benches[current_bench][current_config] = current_time
+                else:
+                    benches[current_bench] = {current_config : current_time}
+    
+    return benches
+
+def usage():
+    """Prints simple usage information."""
+    
+    print '-o <file> the old bench output file.'
+    print '-n <file> the new bench output file.'
+    print '-h causes headers to be output.'
+    print '-f <fieldSpec> which fields to output and in what order.'
+    print '   Not specifying is the same as -f "bcondp".'
+    print '  b: bench'
+    print '  c: config'
+    print '  o: old time'
+    print '  n: new time'
+    print '  d: diff'
+    print '  p: percent diff'
+    
+    
+def main():
+    """Parses command line and writes output."""
+    
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "f:o:n:h")
+    except getopt.GetoptError, err:
+        print str(err) 
+        usage()
+        sys.exit(2)
+    
+    column_formats = {
+        'b' : '{bench: >28} ',
+        'c' : '{config: <4} ',
+        'o' : '{old_time: >10.2f} ',
+        'n' : '{new_time: >10.2f} ',
+        'd' : '{diff: >+10.2f} ',
+        'p' : '{diffp: >+7.1%} ',
+    }
+    header_formats = {
+        'b' : '{bench: >28} ',
+        'c' : '{config: <4} ',
+        'o' : '{old_time: >10} ',
+        'n' : '{new_time: >10} ',
+        'd' : '{diff: >10} ',
+        'p' : '{diffp: >7} ',
+    }
+    
+    old = None
+    new = None
+    column_format = ""
+    header_format = ""
+    columns = 'bcondp'
+    header = False
+    
+    for option, value in opts:
+        if option == "-o":
+            old = value
+        elif option == "-n":
+            new = value
+        elif option == "-h":
+            header = True
+        elif option == "-f":
+            columns = value
+        else:
+            usage()
+            assert False, "unhandled option"
+    
+    if old is None or new is None:
+        usage()
+        sys.exit(2)
+    
+    for column_char in columns:
+        if column_formats[column_char]:
+            column_format += column_formats[column_char]
+            header_format += header_formats[column_char]
+        else:
+            usage()
+            sys.exit(2)
+    
+    if header:
+        print header_format.format(
+            bench='bench'
+            , config='conf'
+            , old_time='old'
+            , new_time='new'
+            , diff='diff'
+            , diffp='diffP'
+        )
+    
+    old_benches = parse(open(old, 'r'))
+    new_benches = parse(open(new, 'r'))
+    
+    for old_bench, old_configs in old_benches.items():
+        if old_bench in new_benches:
+            new_configs = new_benches[old_bench]
+            for old_config, old_time in old_configs.items():
+                if old_config in new_configs:
+                    new_time = new_configs[old_config]
+                    old_time = old_configs[old_config]
+                    print column_format.format(
+                        bench=old_bench.strip()
+                        , config=old_config.strip()
+                        , old_time=old_time
+                        , new_time=new_time
+                        , diff=(old_time - new_time)
+                        , diffp=((old_time-new_time)/old_time)
+                    )
+    
+    
+if __name__ == "__main__":
+    main()
index 38724c1..066573a 100644 (file)
@@ -66,7 +66,7 @@ public:
         }
         return NULL;
     }
-    
+
 private:
     const BenchRegistry* fBench;
     void* fParam;
@@ -106,7 +106,7 @@ static void saveFile(const char name[], const char config[], const char dir[],
             *p++ = c | (SK_A32_MASK << SK_A32_SHIFT);
         }
     }
-
+    
     SkString str;
     make_filename(name, &str);
     str.appendf("_%s.png", config);
@@ -122,7 +122,7 @@ static void performClip(SkCanvas* canvas, int w, int h) {
     r.set(SkIntToScalar(10), SkIntToScalar(10),
           SkIntToScalar(w*2/3), SkIntToScalar(h*2/3));
     canvas->clipRect(r, SkRegion::kIntersect_Op);
-
+    
     r.set(SkIntToScalar(w/3), SkIntToScalar(h/3),
           SkIntToScalar(w-10), SkIntToScalar(h-10));
     canvas->clipRect(r, SkRegion::kXOR_Op);
@@ -166,7 +166,7 @@ static SkDevice* make_device(SkBitmap::Config config, const SkIPoint& size,
     SkDevice* device = NULL;
     SkBitmap bitmap;
     bitmap.setConfig(config, size.fX, size.fY);
-
+    
     switch (backend) {
         case kRaster_Backend:
             bitmap.allocPixels();
@@ -205,7 +205,7 @@ static int findConfig(const char config[]) {
 
 int main (int argc, char * const argv[]) {
     SkAutoGraphics ag;
-
+    
     SkTDict<const char*> defineDict(1024);
     int repeatDraw = 1;
     int forceAlpha = 0xFF;
@@ -218,13 +218,13 @@ int main (int argc, char * const argv[]) {
     const char* matchStr = NULL;
     bool hasStrokeWidth = false;
     float strokeWidth;
-
+    
     SkString outDir;
     SkBitmap::Config outConfig = SkBitmap::kNo_Config;
     const char* configName = "";
     Backend backend = kRaster_Backend;  // for warning
     int configCount = SK_ARRAY_COUNT(gConfigs);
-
+    
     char* const* stop = argv + argc;
     for (++argv; argv < stop; ++argv) {
         if (strcmp(*argv, "-o") == 0) {
@@ -331,7 +331,7 @@ int main (int argc, char * const argv[]) {
             return -1;
         }
     }
-
+    
     // report our current settings
     {
         SkString str;
@@ -339,7 +339,7 @@ int main (int argc, char * const argv[]) {
                    forceAlpha, forceAA, forceFilter);
         log_progress(str);
     }
-
+    
     GrContext* context = NULL;
     SkEGLContext eglContext;
     if (eglContext.init(1024, 1024)) {
@@ -361,34 +361,34 @@ int main (int argc, char * const argv[]) {
         if (hasStrokeWidth) {
             bench->setStrokeWidth(strokeWidth);
         }
-
+        
         // only run benchmarks if their name contains matchStr
         if (matchStr && strstr(bench->getName(), matchStr) == NULL) {
             continue;
         }
-
+        
         {
             SkString str;
             str.printf("running bench [%d %d] %28s", dim.fX, dim.fY,
                        bench->getName());
             log_progress(str);
         }
-
+        
         for (int configIndex = 0; configIndex < configCount; configIndex++) {
             if (configCount > 1) {
                 outConfig = gConfigs[configIndex].fConfig;
                 configName = gConfigs[configIndex].fName;
                 backend = gConfigs[configIndex].fBackend;
             }
-
+            
             if (kGPU_Backend == backend && NULL == context) {
                 continue;
             }
-
+            
             SkDevice* device = make_device(outConfig, dim, backend, context);
             SkCanvas canvas(device);
             device->unref();
-
+            
             if (doClip) {
                 performClip(&canvas, dim.fX, dim.fY);
             }
@@ -398,21 +398,27 @@ int main (int argc, char * const argv[]) {
             if (doRotate) {
                 performRotate(&canvas, dim.fX, dim.fY);
             }
-
+            
+            //warm up caches if needed
             if (repeatDraw > 1) {
                 SkAutoCanvasRestore acr(&canvas, true);
                 bench->draw(&canvas);
+                if (kGPU_Backend == backend && context) {
+                    context->flush();
+                    glFinish();
+                }
             }
-
+            
             SkMSec now = SkTime::GetMSecs();
             for (int i = 0; i < repeatDraw; i++) {
                 SkAutoCanvasRestore acr(&canvas, true);
                 bench->draw(&canvas);
             }
-            if (context) {
+            if (kGPU_Backend == backend && context) {
                 context->flush();
+                glFinish();
             }
-
+            
             if (repeatDraw > 1) {
                 double duration = SkTime::GetMSecs() - now;
                 SkString str;