Major bench refactoring.
   - Use FLAGS_.
   - Remove outer repeat loop.
   - Tune inner loop automatically.

BUG=skia:1590
R=epoger@google.com, scroggo@google.com

Review URL: https://codereview.chromium.org/23478013

git-svn-id: http://skia.googlecode.com/svn/trunk@11187 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/bench/AAClipBench.cpp b/bench/AAClipBench.cpp
index 276a8ff..3c04bd4 100644
--- a/bench/AAClipBench.cpp
+++ b/bench/AAClipBench.cpp
@@ -23,10 +23,6 @@
     bool     fDoPath;
     bool     fDoAA;
 
-    enum {
-        N = SkBENCHLOOP(200),
-    };
-
 public:
     AAClipBench(void* param, bool doPath, bool doAA)
         : INHERITED(param)
@@ -53,7 +49,7 @@
         SkPaint paint;
         this->setupPaint(&paint);
 
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             // jostle the clip regions each time to prevent caching
             fClipRect.offset((i % 2) == 0 ? SkIntToScalar(10) : SkIntToScalar(-10), 0);
             fClipPath.reset();
@@ -96,7 +92,6 @@
     SkRect   fDrawRect;
     SkRandom fRandom;
 
-    static const int kNumDraws = SkBENCHLOOP(2);
     static const int kNestingDepth = 3;
     static const int kImageSize = 400;
 
@@ -169,7 +164,7 @@
 
     virtual void onDraw(SkCanvas* canvas) {
 
-        for (int i = 0; i < kNumDraws; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkPoint offset = SkPoint::Make(0, 0);
             this->recurse(canvas, 0, offset);
         }
@@ -188,10 +183,6 @@
     bool     fDoPath;
     bool     fDoAA;
 
-    enum {
-        N = SkBENCHLOOP(200),
-    };
-
 public:
     AAClipBuilderBench(void* param, bool doPath, bool doAA) : INHERITED(param) {
         fDoPath = doPath;
@@ -212,7 +203,7 @@
         SkPaint paint;
         this->setupPaint(&paint);
 
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkAAClip clip;
             if (fDoPath) {
                 clip.setPath(fPath, &fRegion, fDoAA);
@@ -244,16 +235,13 @@
 protected:
     virtual const char* onGetName() { return "aaclip_setregion"; }
     virtual void onDraw(SkCanvas*) {
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkAAClip clip;
             clip.setRegion(fRegion);
         }
     }
 
 private:
-    enum {
-        N = SkBENCHLOOP(400),
-    };
     SkRegion fRegion;
     typedef SkBenchmark INHERITED;
 };
diff --git a/bench/BicubicBench.cpp b/bench/BicubicBench.cpp
index a3a2318..ece7cbe 100644
--- a/bench/BicubicBench.cpp
+++ b/bench/BicubicBench.cpp
@@ -7,7 +7,6 @@
 
 #include "SkBenchmark.h"
 #include "SkCanvas.h"
-#include "SkRandom.h"
 #include "SkShader.h"
 #include "SkString.h"
 #include "SkBicubicImageFilter.h"
@@ -37,14 +36,16 @@
 
         paint.setAntiAlias(true);
 
-        SkRandom rand;
         SkRect r = SkRect::MakeWH(40, 40);
         SkAutoTUnref<SkImageFilter> bicubic(SkBicubicImageFilter::CreateMitchell(fScale));
         paint.setImageFilter(bicubic);
-        canvas->save();
-        canvas->clipRect(r);
-        canvas->drawOval(r, paint);
-        canvas->restore();
+
+        for (int i = 0; i < this->getLoops(); i++) {
+            canvas->save();
+            canvas->clipRect(r);
+            canvas->drawOval(r, paint);
+            canvas->restore();
+        }
     }
 
 private:
diff --git a/bench/BitmapBench.cpp b/bench/BitmapBench.cpp
index a472d24..698a680 100644
--- a/bench/BitmapBench.cpp
+++ b/bench/BitmapBench.cpp
@@ -81,8 +81,6 @@
     bool        fIsVolatile;
     SkBitmap::Config fConfig;
     SkString    fName;
-    enum { BICUBIC_DUR_SCALE = 20 };
-    enum { N = SkBENCHLOOP(15 * BICUBIC_DUR_SCALE) };
     enum { W = 128 };
     enum { H = 128 };
 public:
@@ -146,14 +144,7 @@
         const SkScalar x0 = SkIntToScalar(-bitmap.width() / 2);
         const SkScalar y0 = SkIntToScalar(-bitmap.height() / 2);
 
-        int count = N;
-#ifdef SK_RELEASE
-        // in DEBUG, N is always 1
-        if (SkPaint::kHigh_FilterLevel == paint.getFilterLevel()) {
-            count /= BICUBIC_DUR_SCALE;
-        }
-#endif
-        for (int i = 0; i < count; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
             SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
 
@@ -164,17 +155,6 @@
         }
     }
 
-    virtual float onGetDurationScale() SK_OVERRIDE {
-        SkPaint paint;
-        this->setupPaint(&paint);
-#ifdef SK_DEBUG
-        return 1;
-#else
-        return SkPaint::kHigh_FilterLevel == paint.getFilterLevel() ?
-                (float)BICUBIC_DUR_SCALE : 1;
-#endif
-    }
-
     virtual void onDrawIntoBitmap(const SkBitmap& bm) {
         const int w = bm.width();
         const int h = bm.height();
@@ -219,7 +199,6 @@
 class FilterBitmapBench : public BitmapBench {
     uint32_t    fFlags;
     SkString    fFullName;
-    enum { N = SkBENCHLOOP(300) };
 public:
     FilterBitmapBench(void* param, bool isOpaque, SkBitmap::Config c,
                       bool forceUpdate, bool isVolitile, uint32_t flags)
diff --git a/bench/BitmapRectBench.cpp b/bench/BitmapRectBench.cpp
index c147da2..f917445 100644
--- a/bench/BitmapRectBench.cpp
+++ b/bench/BitmapRectBench.cpp
@@ -47,7 +47,6 @@
     SkRect      fSrcR, fDstR;
     static const int kWidth = 128;
     static const int kHeight = 128;
-    enum { N = SkBENCHLOOP(300) };
 public:
     BitmapRectBench(void* param, U8CPU alpha, bool doFilter, bool slightMatrix) : INHERITED(param) {
         fAlpha = SkToU8(alpha);
@@ -93,7 +92,7 @@
         paint.setFilterBitmap(fDoFilter);
         paint.setAlpha(fAlpha);
 
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             canvas->drawBitmapRectToRect(fBitmap, &fSrcR, fDstR, &paint);
         }
     }
diff --git a/bench/BitmapScaleBench.cpp b/bench/BitmapScaleBench.cpp
index 2187346..62f8d1b 100644
--- a/bench/BitmapScaleBench.cpp
+++ b/bench/BitmapScaleBench.cpp
@@ -75,7 +75,7 @@
 
         preBenchSetup();
 
-        for (int i = 0; i < SkBENCHLOOP(fLoopCount); i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             doScaleImage();
         }
     }
diff --git a/bench/BlurBench.cpp b/bench/BlurBench.cpp
index b373df8..0ac0b53 100644
--- a/bench/BlurBench.cpp
+++ b/bench/BlurBench.cpp
@@ -60,7 +60,7 @@
         paint.setAntiAlias(true);
 
         SkRandom rand;
-        for (int i = 0; i < SkBENCHLOOP(10); i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400,
                                       rand.nextUScalar1() * 400);
             r.offset(fRadius, fRadius);
diff --git a/bench/BlurImageFilterBench.cpp b/bench/BlurImageFilterBench.cpp
index 10320e8..3d69147 100644
--- a/bench/BlurImageFilterBench.cpp
+++ b/bench/BlurImageFilterBench.cpp
@@ -44,7 +44,10 @@
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
         SkPaint paint;
         paint.setImageFilter(new SkBlurImageFilter(fSigmaX, fSigmaY))->unref();
-        canvas->drawBitmap(fCheckerboard, 0, 0, &paint);
+
+        for (int i = 0; i < this->getLoops(); i++) {
+            canvas->drawBitmap(fCheckerboard, 0, 0, &paint);
+        }
     }
 
 private:
diff --git a/bench/BlurRectBench.cpp b/bench/BlurRectBench.cpp
index ccff8e3..5de16cd 100644
--- a/bench/BlurRectBench.cpp
+++ b/bench/BlurRectBench.cpp
@@ -62,7 +62,7 @@
 
         preBenchSetup(r);
 
-        for (int i = 0; i < SkBENCHLOOP(fLoopCount); i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             makeBlurryRect(r);
         }
     }
diff --git a/bench/ChartBench.cpp b/bench/ChartBench.cpp
index 1ecf30a..6990049 100644
--- a/bench/ChartBench.cpp
+++ b/bench/ChartBench.cpp
@@ -127,7 +127,7 @@
             }
         }
 
-        for (int frame = 0; frame < kFramesPerRun; ++frame) {
+        for (int frame = 0; frame < this->getLoops(); ++frame) {
 
             canvas->clear(0xFFE0F0E0);
 
@@ -183,8 +183,6 @@
         kNumGraphs = 5,
         kPixelsPerTick = 3,
         kShiftPerFrame = 1,
-
-        kFramesPerRun = SkBENCHLOOP(5),
     };
     int                 fShift;
     SkISize             fSize;
diff --git a/bench/ChecksumBench.cpp b/bench/ChecksumBench.cpp
index 315402e..7cc6008 100644
--- a/bench/ChecksumBench.cpp
+++ b/bench/ChecksumBench.cpp
@@ -23,7 +23,6 @@
     enum {
         U32COUNT  = 256,
         SIZE      = U32COUNT * 4,
-        N         = SkBENCHLOOP(100000),
     };
     uint32_t    fData[U32COUNT];
     ChecksumType fType;
@@ -52,13 +51,13 @@
     virtual void onDraw(SkCanvas*) {
         switch (fType) {
             case kChecksum_ChecksumType: {
-                for (int i = 0; i < N; i++) {
+                for (int i = 0; i < this->getLoops(); i++) {
                     volatile uint32_t result = SkChecksum::Compute(fData, sizeof(fData));
                     sk_ignore_unused_variable(result);
                 }
             } break;
             case kMD5_ChecksumType: {
-                for (int i = 0; i < N; i++) {
+                for (int i = 0; i < this->getLoops(); i++) {
                     SkMD5 md5;
                     md5.update(reinterpret_cast<uint8_t*>(fData), sizeof(fData));
                     SkMD5::Digest digest;
@@ -66,7 +65,7 @@
                 }
             } break;
             case kSHA1_ChecksumType: {
-                for (int i = 0; i < N; i++) {
+                for (int i = 0; i < this->getLoops(); i++) {
                     SkSHA1 sha1;
                     sha1.update(reinterpret_cast<uint8_t*>(fData), sizeof(fData));
                     SkSHA1::Digest digest;
@@ -74,7 +73,7 @@
                 }
             } break;
             case kMurmur3_ChecksumType: {
-                for (int i = 0; i < N; i++) {
+                for (int i = 0; i < this->getLoops(); i++) {
                     volatile uint32_t result = SkChecksum::Murmur3(fData, sizeof(fData));
                     sk_ignore_unused_variable(result);
                 }
diff --git a/bench/ChromeBench.cpp b/bench/ChromeBench.cpp
index 8021f92..fb6dcb2 100644
--- a/bench/ChromeBench.cpp
+++ b/bench/ChromeBench.cpp
@@ -468,7 +468,7 @@
         for (int i = 0; i < N; i++) {
             SkRect current;
             setRectangle(current, i);
-            for (int j = 0; j < SkBENCHLOOP(gmailScrollingRectSpec[i*3]); j++) {
+            for (int j = 0; j < this->getLoops() * gmailScrollingRectSpec[i*3]; j++) {
                 canvas->drawRect(current, paint);
             }
         }
diff --git a/bench/CmapBench.cpp b/bench/CmapBench.cpp
index 49c2aee..c721e9c 100644
--- a/bench/CmapBench.cpp
+++ b/bench/CmapBench.cpp
@@ -11,7 +11,6 @@
 #include "SkTypeface.h"
 
 enum {
-    LOOP = SkBENCHLOOP(1000),
     NGLYPHS = 100
 };
 
@@ -21,44 +20,44 @@
     return (SkTypeface::Encoding)enc;
 }
 
-typedef void (*TypefaceProc)(const SkPaint&, const void* text, size_t len,
+typedef void (*TypefaceProc)(int loops, const SkPaint&, const void* text, size_t len,
                              int glyphCount);
 
-static void containsText_proc(const SkPaint& paint, const void* text, size_t len,
+static void containsText_proc(int loops, const SkPaint& paint, const void* text, size_t len,
                               int glyphCount) {
-    for (int i = 0; i < LOOP; ++i) {
+    for (int i = 0; i < loops; ++i) {
         paint.containsText(text, len);
     }
 }
 
-static void textToGlyphs_proc(const SkPaint& paint, const void* text, size_t len,
+static void textToGlyphs_proc(int loops, const SkPaint& paint, const void* text, size_t len,
                               int glyphCount) {
     uint16_t glyphs[NGLYPHS];
     SkASSERT(glyphCount <= NGLYPHS);
 
-    for (int i = 0; i < LOOP; ++i) {
+    for (int i = 0; i < loops; ++i) {
         paint.textToGlyphs(text, len, glyphs);
     }
 }
 
-static void charsToGlyphs_proc(const SkPaint& paint, const void* text,
+static void charsToGlyphs_proc(int loops, const SkPaint& paint, const void* text,
                                size_t len, int glyphCount) {
     SkTypeface::Encoding encoding = paint2Encoding(paint);
     uint16_t glyphs[NGLYPHS];
     SkASSERT(glyphCount <= NGLYPHS);
 
     SkTypeface* face = paint.getTypeface();
-    for (int i = 0; i < LOOP; ++i) {
+    for (int i = 0; i < loops; ++i) {
         face->charsToGlyphs(text, encoding, glyphs, glyphCount);
     }
 }
 
-static void charsToGlyphsNull_proc(const SkPaint& paint, const void* text,
+static void charsToGlyphsNull_proc(int loops, const SkPaint& paint, const void* text,
                                    size_t len, int glyphCount) {
     SkTypeface::Encoding encoding = paint2Encoding(paint);
 
     SkTypeface* face = paint.getTypeface();
-    for (int i = 0; i < LOOP; ++i) {
+    for (int i = 0; i < loops; ++i) {
         face->charsToGlyphs(text, encoding, NULL, glyphCount);
     }
 }
@@ -87,7 +86,7 @@
     }
 
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
-        fProc(fPaint, fText, sizeof(fText), NGLYPHS);
+        fProc(this->getLoops(), fPaint, fText, sizeof(fText), NGLYPHS);
     }
 
 private:
diff --git a/bench/ColorFilterBench.cpp b/bench/ColorFilterBench.cpp
index 22a0472..2ac78ae 100644
--- a/bench/ColorFilterBench.cpp
+++ b/bench/ColorFilterBench.cpp
@@ -76,11 +76,14 @@
         SkRect r = getFilterRect();
         SkPaint paint;
         paint.setColor(SK_ColorRED);
-        for (float brightness = -1.0f; brightness <= 1.0f; brightness += 0.4f) {
-            SkAutoTUnref<SkImageFilter> dim(make_brightness(-brightness));
-            SkAutoTUnref<SkImageFilter> bright(make_brightness(brightness, dim));
-            paint.setImageFilter(bright);
-            canvas->drawRect(r, paint);
+
+        for (int i = 0; i < this->getLoops(); i++) {
+            for (float brightness = -1.0f; brightness <= 1.0f; brightness += 0.4f) {
+                SkAutoTUnref<SkImageFilter> dim(make_brightness(-brightness));
+                SkAutoTUnref<SkImageFilter> bright(make_brightness(brightness, dim));
+                paint.setImageFilter(bright);
+                canvas->drawRect(r, paint);
+            }
         }
     }
 
@@ -103,7 +106,7 @@
         SkRect r = getFilterRect();
         SkPaint paint;
         paint.setColor(SK_ColorRED);
-        {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkAutoTUnref<SkImageFilter> brightness(make_brightness(0.9f));
             SkAutoTUnref<SkImageFilter> grayscale(make_grayscale(brightness));
             paint.setImageFilter(grayscale);
@@ -130,7 +133,7 @@
         SkRect r = getFilterRect();
         SkPaint paint;
         paint.setColor(SK_ColorRED);
-        {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkAutoTUnref<SkImageFilter> grayscale(make_grayscale());
             SkAutoTUnref<SkImageFilter> brightness(make_brightness(0.9f, grayscale));
             paint.setImageFilter(brightness);
@@ -157,7 +160,7 @@
         SkRect r = getFilterRect();
         SkPaint paint;
         paint.setColor(SK_ColorRED);
-        {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkAutoTUnref<SkImageFilter> blue(make_mode_blue());
             SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f, blue));
             paint.setImageFilter(brightness);
@@ -184,7 +187,7 @@
         SkRect r = getFilterRect();
         SkPaint paint;
         paint.setColor(SK_ColorRED);
-        {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f));
             SkAutoTUnref<SkImageFilter> blue(make_mode_blue(brightness));
             paint.setImageFilter(blue);
@@ -211,7 +214,7 @@
         SkRect r = getFilterRect();
         SkPaint paint;
         paint.setColor(SK_ColorRED);
-        {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkAutoTUnref<SkImageFilter> brightness(make_brightness(1.0f));
             paint.setImageFilter(brightness);
             canvas->drawRect(r, paint);
@@ -237,7 +240,7 @@
         SkRect r = getFilterRect();
         SkPaint paint;
         paint.setColor(SK_ColorRED);
-        {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkAutoTUnref<SkImageFilter> blue(make_mode_blue());
             paint.setImageFilter(blue);
             canvas->drawRect(r, paint);
@@ -263,7 +266,7 @@
         SkRect r = getFilterRect();
         SkPaint paint;
         paint.setColor(SK_ColorRED);
-        {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkAutoTUnref<SkImageFilter> grayscale(make_grayscale());
             paint.setImageFilter(grayscale);
             canvas->drawRect(r, paint);
@@ -289,7 +292,7 @@
         SkRect r = getFilterRect();
         SkPaint paint;
         paint.setColor(SK_ColorRED);
-        {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkAutoTUnref<SkColorFilter> table_filter(make_table_filter());
             paint.setColorFilter(table_filter);
             canvas->drawRect(r, paint);
diff --git a/bench/DashBench.cpp b/bench/DashBench.cpp
index 0fcde31..84fe3ab 100644
--- a/bench/DashBench.cpp
+++ b/bench/DashBench.cpp
@@ -37,9 +37,6 @@
     SkPoint             fPts[2];
     bool                fDoClip;
 
-    enum {
-        N = SkBENCHLOOP(100)
-    };
 public:
     DashBench(void* param, const SkScalar intervals[], int count, int width,
               bool doClip = false) : INHERITED(param) {
@@ -85,7 +82,7 @@
             canvas->clipRect(r);
         }
 
-        this->handlePath(canvas, path, paint, N);
+        this->handlePath(canvas, path, paint, this->getLoops());
     }
 
     virtual void handlePath(SkCanvas* canvas, const SkPath& path,
@@ -183,10 +180,6 @@
     SkPath   fPath;
     SkAutoTUnref<SkPathEffect> fPE;
 
-    enum {
-        N = SkBENCHLOOP(400)
-    };
-
 public:
     MakeDashBench(void* param, void (*proc)(SkPath*), const char name[]) : INHERITED(param) {
         fName.printf("makedash_%s", name);
@@ -203,7 +196,7 @@
 
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
         SkPath dst;
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkStrokeRec rec(SkStrokeRec::kHairline_InitStyle);
 
             fPE->filterPath(&dst, fPath, &rec, NULL);
@@ -224,10 +217,6 @@
     bool     fIsRound;
     SkAutoTUnref<SkPathEffect> fPE;
 
-    enum {
-        N = SkBENCHLOOP(200)
-    };
-
 public:
     DashLineBench(void* param, SkScalar width, bool isRound) : INHERITED(param) {
         fName.printf("dashline_%g_%s", SkScalarToFloat(width), isRound ? "circle" : "square");
@@ -249,7 +238,7 @@
         paint.setStrokeWidth(fStrokeWidth);
         paint.setStrokeCap(fIsRound ? SkPaint::kRound_Cap : SkPaint::kSquare_Cap);
         paint.setPathEffect(fPE);
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             canvas->drawLine(10 * SK_Scalar1, 10 * SK_Scalar1,
                              640 * SK_Scalar1, 10 * SK_Scalar1, paint);
         }
@@ -266,10 +255,6 @@
 
     SkAutoTUnref<SkPathEffect> fPathEffect;
 
-    enum {
-        N = SkBENCHLOOP(480)
-    };
-
 public:
     DrawPointsDashingBench(void* param, int dashLength, int strokeWidth, bool doAA)
         : INHERITED(param) {
@@ -287,7 +272,6 @@
     }
 
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
-
         SkPaint p;
         this->setupPaint(&p);
         p.setColor(SK_ColorBLACK);
@@ -301,8 +285,7 @@
             { SkIntToScalar(640), 0 }
         };
 
-        for (int i = 0; i < N; ++i) {
-
+        for (int i = 0; i < this->getLoops(); ++i) {
             pts[0].fY = pts[1].fY = SkIntToScalar(i % 480);
             canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, p);
         }
@@ -381,7 +364,9 @@
         p.setStrokeWidth(fStrokeWidth);
         p.setPathEffect(fPathEffect);
 
-        canvas->drawPoints(SkCanvas::kLines_PointMode, 2, fPts, p);
+        for (int i = 0; i < this->getLoops(); i++) {
+            canvas->drawPoints(SkCanvas::kLines_PointMode, 2, fPts, p);
+        }
     }
 
 private:
diff --git a/bench/DecodeBench.cpp b/bench/DecodeBench.cpp
index c87e6f6..c45654c 100644
--- a/bench/DecodeBench.cpp
+++ b/bench/DecodeBench.cpp
@@ -7,29 +7,26 @@
  */
 #include "SkBenchmark.h"
 #include "SkBitmap.h"
+#include "SkCommandLineFlags.h"
 #include "SkImageDecoder.h"
 #include "SkString.h"
 
+DEFINE_string(decodeBenchFilename, "resources/CMYK.jpeg", "Path to image for DecodeBench.");
+
 static const char* gConfigName[] = {
     "ERROR", "a1", "a8", "index8", "565", "4444", "8888"
 };
 
 class DecodeBench : public SkBenchmark {
-    const char* fFilename;
     SkBitmap::Config fPrefConfig;
     SkString fName;
-    enum { N = SkBENCHLOOP(10) };
 public:
     DecodeBench(void* param, SkBitmap::Config c) : SkBenchmark(param) {
-        fFilename = this->findDefine("decode-filename");
         fPrefConfig = c;
 
-        const char* fname = NULL;
-        if (fFilename) {
-            fname = strrchr(fFilename, '/');
-            if (fname) {
-                fname += 1; // skip the slash
-            }
+        const char* fname = strrchr(FLAGS_decodeBenchFilename[0], '/');
+        if (fname) {
+            fname++; // skip the slash
         }
         fName.printf("decode_%s_%s", gConfigName[c], fname);
         fIsRendering = false;
@@ -41,12 +38,12 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        if (fFilename) {
-            for (int i = 0; i < N; i++) {
-                SkBitmap bm;
-                SkImageDecoder::DecodeFile(fFilename, &bm, fPrefConfig,
-                                           SkImageDecoder::kDecodePixels_Mode);
-            }
+        for (int i = 0; i < this->getLoops(); i++) {
+            SkBitmap bm;
+            SkImageDecoder::DecodeFile(FLAGS_decodeBenchFilename[0],
+                                       &bm,
+                                       fPrefConfig,
+                                       SkImageDecoder::kDecodePixels_Mode);
         }
     }
 
diff --git a/bench/DeferredCanvasBench.cpp b/bench/DeferredCanvasBench.cpp
index e14bb24..4caf229 100644
--- a/bench/DeferredCanvasBench.cpp
+++ b/bench/DeferredCanvasBench.cpp
@@ -16,7 +16,6 @@
     }
 
     enum {
-        N = SkBENCHLOOP(25), // number of times to create the picture
         CANVAS_WIDTH = 200,
         CANVAS_HEIGHT = 200,
     };
@@ -34,7 +33,7 @@
 
         initDeferredCanvas(deferredCanvas);
 
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             drawInDeferredCanvas(deferredCanvas);
         }
 
@@ -75,9 +74,6 @@
         : INHERITED(param, "record") {
     }
 
-    enum {
-        M = SkBENCHLOOP(700),   // number of individual draws in each loop
-    };
 protected:
 
     virtual void initDeferredCanvas(SkDeferredCanvas* canvas) SK_OVERRIDE {
@@ -88,7 +84,7 @@
         SkRect rect;
         rect.setXYWH(0, 0, 10, 10);
         SkPaint paint;
-        for (int i = 0; i < M; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             canvas->save(SkCanvas::kMatrixClip_SaveFlag);
             canvas->translate(SkIntToScalar(i * 27 % CANVAS_WIDTH), SkIntToScalar(i * 13 % CANVAS_HEIGHT));
             canvas->drawRect(rect, paint);
diff --git a/bench/DeferredSurfaceCopyBench.cpp b/bench/DeferredSurfaceCopyBench.cpp
index cbf96d0..7c9abea 100644
--- a/bench/DeferredSurfaceCopyBench.cpp
+++ b/bench/DeferredSurfaceCopyBench.cpp
@@ -17,7 +17,6 @@
 
 class DeferredSurfaceCopyBench : public SkBenchmark {
     enum {
-        N = SkBENCHLOOP(5),
         kSurfaceWidth = 1000,
         kSurfaceHeight = 1000,
     };
@@ -56,7 +55,7 @@
         SkAutoTUnref<SkDeferredCanvas> drawingCanvas(SkDeferredCanvas::Create(surface));
         surface->unref();
 
-        for (int iteration = 0; iteration < N; iteration++) {
+        for (int iteration = 0; iteration < this->getLoops(); iteration++) {
             drawingCanvas->clear(0);
             SkAutoTUnref<SkImage> image(drawingCanvas->newImageSnapshot());
             SkPaint paint;
diff --git a/bench/DisplacementBench.cpp b/bench/DisplacementBench.cpp
index e498a1b..bf1ee73 100644
--- a/bench/DisplacementBench.cpp
+++ b/bench/DisplacementBench.cpp
@@ -105,7 +105,10 @@
         paint.setImageFilter(SkNEW_ARGS(SkDisplacementMapEffect,
             (SkDisplacementMapEffect::kR_ChannelSelectorType,
              SkDisplacementMapEffect::kG_ChannelSelectorType, 0.0f, displ)))->unref();
-        drawClippedBitmap(canvas, 0, 0, paint);
+
+        for (int i = 0; i < this->getLoops(); i++) {
+            drawClippedBitmap(canvas, 0, 0, paint);
+        }
     }
 
 private:
@@ -129,7 +132,9 @@
         paint.setImageFilter(SkNEW_ARGS(SkDisplacementMapEffect,
             (SkDisplacementMapEffect::kB_ChannelSelectorType,
              SkDisplacementMapEffect::kA_ChannelSelectorType, 16.0f, displ)))->unref();
-        drawClippedBitmap(canvas, 100, 0, paint);
+        for (int i = 0; i < this->getLoops(); i++) {
+            drawClippedBitmap(canvas, 100, 0, paint);
+        }
     }
 
 private:
@@ -153,7 +158,9 @@
         paint.setImageFilter(SkNEW_ARGS(SkDisplacementMapEffect,
             (SkDisplacementMapEffect::kR_ChannelSelectorType,
              SkDisplacementMapEffect::kB_ChannelSelectorType, 32.0f, displ)))->unref();
-        drawClippedBitmap(canvas, 200, 0, paint);
+        for (int i = 0; i < this->getLoops(); i++) {
+            drawClippedBitmap(canvas, 200, 0, paint);
+        }
     }
 
 private:
diff --git a/bench/FSRectBench.cpp b/bench/FSRectBench.cpp
index 5ae4c2f..0083dd4 100644
--- a/bench/FSRectBench.cpp
+++ b/bench/FSRectBench.cpp
@@ -44,9 +44,9 @@
 
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
         SkPaint paint;
-        for (int i = 0; i < N; ++i) {
-            paint.setColor(fColors[i]);
-            canvas->drawRect(fRects[i], paint);
+        for (int i = 0; i < this->getLoops(); ++i) {
+            paint.setColor(fColors[i % N]);
+            canvas->drawRect(fRects[i % N], paint);
         }
     }
 
@@ -54,7 +54,7 @@
     enum {
         W = 640,
         H = 480,
-        N = SkBENCHLOOP(300)
+        N = 300,
     };
     SkRect  fRects[N];
     SkColor fColors[N];
diff --git a/bench/FontCacheBench.cpp b/bench/FontCacheBench.cpp
index c6aab7a..c206d5b 100644
--- a/bench/FontCacheBench.cpp
+++ b/bench/FontCacheBench.cpp
@@ -24,10 +24,6 @@
 }
 
 class FontCacheBench : public SkBenchmark {
-    enum {
-        N = SkBENCHLOOP(50)
-    };
-
 public:
     FontCacheBench(void* param) : INHERITED(param) {}
 
@@ -44,7 +40,7 @@
         const uint16_t* array = gUniqueGlyphIDs;
         while (*array != gUniqueGlyphIDs_Sentinel) {
             size_t count = count_glyphs(array);
-            for (int i = 0; i < N; ++i) {
+            for (int i = 0; i < this->getLoops(); ++i) {
                 paint.measureText(array, count * sizeof(uint16_t));
             }
             array += count + 1;    // skip the sentinel
diff --git a/bench/FontScalerBench.cpp b/bench/FontScalerBench.cpp
index 4ac6a35..ac4f60e 100644
--- a/bench/FontScalerBench.cpp
+++ b/bench/FontScalerBench.cpp
@@ -35,14 +35,16 @@
         bool prev = gSkSuppressFontCachePurgeSpew;
         gSkSuppressFontCachePurgeSpew = true;
 
-        // this is critical - we want to time the creation process, so we
-        // explicitly flush our cache before each run
-        SkGraphics::PurgeFontCache();
+        for (int i = 0; i < this->getLoops(); i++) {
+            // this is critical - we want to time the creation process, so we
+            // explicitly flush our cache before each run
+            SkGraphics::PurgeFontCache();
 
-        for (int ps = 9; ps <= 24; ps += 2) {
-            paint.setTextSize(SkIntToScalar(ps));
-            canvas->drawText(fText.c_str(), fText.size(),
-                             0, SkIntToScalar(20), paint);
+            for (int ps = 9; ps <= 24; ps += 2) {
+                paint.setTextSize(SkIntToScalar(ps));
+                canvas->drawText(fText.c_str(), fText.size(),
+                        0, SkIntToScalar(20), paint);
+            }
         }
 
         gSkSuppressFontCachePurgeSpew = prev;
diff --git a/bench/GameBench.cpp b/bench/GameBench.cpp
index 44f92cb..5fc9c03 100644
--- a/bench/GameBench.cpp
+++ b/bench/GameBench.cpp
@@ -144,8 +144,7 @@
                                                   SkShader::kClamp_TileMode,
                                                   SkShader::kClamp_TileMode))->unref();
 
-        for (int i = 0; i < kNumRects; ++i, ++fNumSaved) {
-
+        for (int i = 0; i < this->getLoops(); ++i, ++fNumSaved) {
             if (0 == i % kNumBeforeClear) {
                 if (kPartial_Clear == fClear) {
                     for (int j = 0; j < fNumSaved; ++j) {
@@ -229,15 +228,7 @@
                                        (kNumAtlasedX+1) * kAtlasSpacer;
     static const int kTotAtlasHeight = kNumAtlasedY * kAtlasCellHeight +
                                        (kNumAtlasedY+1) * kAtlasSpacer;
-
-#ifdef SK_DEBUG
-    static const int kNumRects = 100;
-    static const int kNumBeforeClear = 10;
-#else
-    static const int kNumRects = 5000;
-    static const int kNumBeforeClear = 300;
-#endif
-
+    static const int kNumBeforeClear = 100;
 
     Type     fType;
     Clear    fClear;
diff --git a/bench/GrMemoryPoolBench.cpp b/bench/GrMemoryPoolBench.cpp
index dccf827..5ad1afa 100644
--- a/bench/GrMemoryPoolBench.cpp
+++ b/bench/GrMemoryPoolBench.cpp
@@ -34,9 +34,6 @@
  * This benchmark creates and deletes objects in stack order
  */
 class GrMemoryPoolBenchStack : public SkBenchmark {
-    enum {
-        N = SkBENCHLOOP(1 * (1 << 20)),
-    };
 public:
     GrMemoryPoolBenchStack(void* param) : INHERITED(param) {
         fIsRendering = false;
@@ -56,13 +53,11 @@
         // We delete if a random [-1, 1] fixed pt is < the thresh. Otherwise,
         // we allocate. We start allocate-biased and ping-pong to delete-biased
         SkFixed delThresh = -SK_FixedHalf;
-        enum {
-            kSwitchThreshPeriod = N / (2 * kMaxObjects),
-        };
+        const int kSwitchThreshPeriod = this->getLoops() / (2 * kMaxObjects);
         int s = 0;
 
         int count = 0;
-        for (int i = 0; i < N; i++, ++s) {
+        for (int i = 0; i < this->getLoops(); i++, ++s) {
             if (kSwitchThreshPeriod == s) {
                 delThresh = -delThresh;
                 s = 0;
@@ -90,9 +85,6 @@
  * This benchmark creates objects and deletes them in random order
  */
 class GrMemoryPoolBenchRandom : public SkBenchmark {
-    enum {
-        N = SkBENCHLOOP(1 * (1 << 20)),
-    };
 public:
     GrMemoryPoolBenchRandom(void* param) : INHERITED(param) {
         fIsRendering = false;
@@ -109,7 +101,7 @@
         };
         SkAutoTDelete<A> objects[kMaxObjects];
 
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             uint32_t idx = r.nextRangeU(0, kMaxObjects-1);
             if (NULL == objects[idx].get()) {
                 objects[idx].reset(new A);
@@ -128,8 +120,7 @@
  */
 class GrMemoryPoolBenchQueue : public SkBenchmark {
     enum {
-        N = SkBENCHLOOP((1 << 8)),
-        M = SkBENCHLOOP(4 * (1 << 10)),
+        M = 4 * (1 << 10),
     };
 public:
     GrMemoryPoolBenchQueue(void* param) : INHERITED(param) {
@@ -143,7 +134,7 @@
     virtual void onDraw(SkCanvas*) {
         SkRandom r;
         A* objects[M];
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             uint32_t count = r.nextRangeU(0, M-1);
             for (uint32_t i = 0; i < count; i++) {
                 objects[i] = new A;
diff --git a/bench/GradientBench.cpp b/bench/GradientBench.cpp
index 773522e..8dec68b 100644
--- a/bench/GradientBench.cpp
+++ b/bench/GradientBench.cpp
@@ -159,11 +159,10 @@
 class GradientBench : public SkBenchmark {
     SkString fName;
     SkShader* fShader;
-    int      fCount;
+    int      fRepeat;
     enum {
         W   = 400,
         H   = 400,
-        N   = 1
     };
 public:
     GradientBench(void* param, GradType gradType,
@@ -187,7 +186,7 @@
             { SkIntToScalar(W), SkIntToScalar(H) }
         };
 
-        fCount = SkBENCHLOOP(N * gGrads[gradType].fRepeat);
+        fRepeat = gGrads[gradType].fRepeat;
         fShader = gGrads[gradType].fMaker(pts, data, tm, NULL, scale);
         fGeomType = geomType;
     }
@@ -208,7 +207,7 @@
         paint.setShader(fShader);
 
         SkRect r = { 0, 0, SkIntToScalar(W), SkIntToScalar(H) };
-        for (int i = 0; i < fCount; i++) {
+        for (int i = 0; i < this->getLoops() * fRepeat; i++) {
             switch (fGeomType) {
                case kRect_GeomType:
                    canvas->drawRect(r, paint);
@@ -251,7 +250,7 @@
             { SkIntToScalar(100), SkIntToScalar(100) },
         };
 
-        for (int i = 0; i < SkBENCHLOOP(1000); i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             const int gray = i % 256;
             const int alpha = fHasAlpha ? gray : 0xFF;
             SkColor colors[] = {
diff --git a/bench/HairlinePathBench.cpp b/bench/HairlinePathBench.cpp
index f5b30a3..3ba0972 100644
--- a/bench/HairlinePathBench.cpp
+++ b/bench/HairlinePathBench.cpp
@@ -63,8 +63,7 @@
             path.transform(m);
         }
 
-        int count = N;
-        for (int i = 0; i < count; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             canvas->drawPath(path, paint);
         }
     }
@@ -73,7 +72,6 @@
     SkPaint     fPaint;
     SkString    fName;
     Flags       fFlags;
-    enum { N = SkBENCHLOOP(200) };
     typedef SkBenchmark INHERITED;
 };
 
diff --git a/bench/ImageCacheBench.cpp b/bench/ImageCacheBench.cpp
index 3a22a47..c0a2d3d 100644
--- a/bench/ImageCacheBench.cpp
+++ b/bench/ImageCacheBench.cpp
@@ -13,7 +13,6 @@
     SkBitmap            fBM;
 
     enum {
-        N = SkBENCHLOOP(1000),
         DIM = 1,
         CACHE_COUNT = 500
     };
@@ -46,7 +45,7 @@
 
         SkBitmap tmp;
         // search for a miss (-1 scale)
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             (void)fCache.findAndLock(fBM, -1, -1, &tmp);
         }
     }
diff --git a/bench/ImageDecodeBench.cpp b/bench/ImageDecodeBench.cpp
index 1cb29b1..2e50ec5 100644
--- a/bench/ImageDecodeBench.cpp
+++ b/bench/ImageDecodeBench.cpp
@@ -59,7 +59,7 @@
 #endif
         // Decode a bunch of times
         SkBitmap bm;
-        for (int i = 0; i < SkBENCHLOOP(1000); ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkDEBUGCODE(bool success =) SkImageDecoder::DecodeStream(&fStream, &bm);
 #ifdef SK_DEBUG
             if (!success) {
diff --git a/bench/InterpBench.cpp b/bench/InterpBench.cpp
index 9b607ad..513618b 100644
--- a/bench/InterpBench.cpp
+++ b/bench/InterpBench.cpp
@@ -33,7 +33,7 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        int n = SkBENCHLOOP(kLoop * this->mulLoopCount());
+        int n = this->getLoops() * this->mulLoopCount();
         for (int i = 0; i < n; i++) {
             this->performTest(fDst, fFx, fDx, kBuffer);
         }
diff --git a/bench/LightingBench.cpp b/bench/LightingBench.cpp
index 9f25434..37c098b 100644
--- a/bench/LightingBench.cpp
+++ b/bench/LightingBench.cpp
@@ -26,7 +26,9 @@
                               SkRect::MakeWH(FILTER_WIDTH_LARGE, FILTER_HEIGHT_LARGE);
         SkPaint paint;
         paint.setImageFilter(imageFilter)->unref();
-        canvas->drawRect(r, paint);
+        for (int i = 0; i < this->getLoops(); i++) {
+            canvas->drawRect(r, paint);
+        }
     }
 
     static SkPoint3 getPointLocation() {
diff --git a/bench/LineBench.cpp b/bench/LineBench.cpp
index feaae2b..7a54d3c 100644
--- a/bench/LineBench.cpp
+++ b/bench/LineBench.cpp
@@ -22,7 +22,6 @@
     SkString    fName;
     enum {
         PTS = 500,
-        N = SkBENCHLOOP(10)
     };
     SkPoint fPts[PTS];
 
@@ -51,7 +50,7 @@
         paint.setAntiAlias(fDoAA);
         paint.setStrokeWidth(fStrokeWidth);
 
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             canvas->drawPoints(SkCanvas::kLines_PointMode, PTS, fPts, paint);
         }
     }
diff --git a/bench/MagnifierBench.cpp b/bench/MagnifierBench.cpp
index 2e937f3..6d48a61 100644
--- a/bench/MagnifierBench.cpp
+++ b/bench/MagnifierBench.cpp
@@ -43,7 +43,10 @@
                                  SkIntToScalar(h / 4),
                                  SkIntToScalar(w / 2),
                                  SkIntToScalar(h / 2)), 100))->unref();
-        canvas->drawBitmap(fCheckerboard, 0, 0, &paint);
+
+        for (int i = 0; i < this->getLoops(); i++) {
+            canvas->drawBitmap(fCheckerboard, 0, 0, &paint);
+        }
     }
 
 private:
diff --git a/bench/MathBench.cpp b/bench/MathBench.cpp
index 32a89d6..7bf7d93 100644
--- a/bench/MathBench.cpp
+++ b/bench/MathBench.cpp
@@ -18,7 +18,6 @@
 class MathBench : public SkBenchmark {
     enum {
         kBuffer = 100,
-        kLoop   = 10000
     };
     SkString    fName;
     float       fSrc[kBuffer], fDst[kBuffer];
@@ -46,7 +45,7 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        int n = SkBENCHLOOP(kLoop * this->mulLoopCount());
+        int n = this->getLoops() * this->mulLoopCount();
         for (int i = 0; i < n; i++) {
             this->performTest(fDst, fSrc, kBuffer);
         }
@@ -247,8 +246,7 @@
 
 class IsFiniteBench : public SkBenchmark {
     enum {
-        N = SkBENCHLOOP(1000),
-        NN = SkBENCHLOOP(1000),
+        N = 1000,
     };
     float fData[N];
 public:
@@ -278,13 +276,13 @@
         int counter = 0;
 
         if (proc) {
-            for (int j = 0; j < NN; ++j) {
+            for (int j = 0; j < this->getLoops(); ++j) {
                 for (int i = 0; i < N - 4; ++i) {
                     counter += proc(&data[i]);
                 }
             }
         } else {
-            for (int j = 0; j < NN; ++j) {
+            for (int j = 0; j < this->getLoops(); ++j) {
                 for (int i = 0; i < N - 4; ++i) {
                     const SkRect* r = reinterpret_cast<const SkRect*>(&data[i]);
                     if (false) { // avoid bit rot, suppress warning
@@ -314,8 +312,7 @@
 
 class FloorBench : public SkBenchmark {
     enum {
-        ARRAY = SkBENCHLOOP(1000),
-        LOOP = SkBENCHLOOP(1000),
+        ARRAY = 1000,
     };
     float fData[ARRAY];
     bool fFast;
@@ -345,14 +342,14 @@
         const float* data = fData;
 
         if (fFast) {
-            for (int j = 0; j < LOOP; ++j) {
+            for (int j = 0; j < this->getLoops(); ++j) {
                 for (int i = 0; i < ARRAY; ++i) {
                     accum += fast_floor(data[i]);
                 }
                 this->process(accum);
             }
         } else {
-            for (int j = 0; j < LOOP; ++j) {
+            for (int j = 0; j < this->getLoops(); ++j) {
                 for (int i = 0; i < ARRAY; ++i) {
                     accum += sk_float_floor(data[i]);
                 }
@@ -373,8 +370,7 @@
 
 class CLZBench : public SkBenchmark {
     enum {
-        ARRAY = SkBENCHLOOP(1000),
-        LOOP = SkBENCHLOOP(5000),
+        ARRAY = 1000,
     };
     uint32_t fData[ARRAY];
     bool fUsePortable;
@@ -405,14 +401,14 @@
         int accum = 0;
 
         if (fUsePortable) {
-            for (int j = 0; j < LOOP; ++j) {
+            for (int j = 0; j < this->getLoops(); ++j) {
                 for (int i = 0; i < ARRAY; ++i) {
                     accum += SkCLZ_portable(fData[i]);
                 }
                 this->process(accum);
             }
         } else {
-            for (int j = 0; j < LOOP; ++j) {
+            for (int j = 0; j < this->getLoops(); ++j) {
                 for (int i = 0; i < ARRAY; ++i) {
                     accum += SkCLZ(fData[i]);
                 }
@@ -435,8 +431,7 @@
 
 class NormalizeBench : public SkBenchmark {
     enum {
-        ARRAY = SkBENCHLOOP(1000),
-        LOOP = SkBENCHLOOP(1000),
+        ARRAY =1000,
     };
     SkVector fVec[ARRAY];
 
@@ -460,7 +455,7 @@
     virtual void onDraw(SkCanvas*) {
         int accum = 0;
 
-        for (int j = 0; j < LOOP; ++j) {
+        for (int j = 0; j < this->getLoops(); ++j) {
             for (int i = 0; i < ARRAY; ++i) {
                 accum += fVec[i].normalize();
             }
@@ -482,8 +477,7 @@
 
 class FixedMathBench : public SkBenchmark {
     enum {
-        N = SkBENCHLOOP(1000),
-        NN = SkBENCHLOOP(1000),
+        N = 1000,
     };
     float fData[N];
     SkFixed fResult[N];
@@ -491,8 +485,8 @@
 
     FixedMathBench(void* param) : INHERITED(param) {
         SkRandom rand;
-        for (int i = 0; i < N; ++i) {
-            fData[i] = rand.nextSScalar1();
+        for (int i = 0; i < this->getLoops(); ++i) {
+            fData[i%N] = rand.nextSScalar1();
         }
 
         fIsRendering = false;
@@ -500,7 +494,7 @@
 
 protected:
     virtual void onDraw(SkCanvas*) {
-        for (int j = 0; j < NN; ++j) {
+        for (int j = 0; j < this->getLoops(); ++j) {
             for (int i = 0; i < N - 4; ++i) {
                 fResult[i] = SkFloatToFixed(fData[i]);
             }
diff --git a/bench/Matrix44Bench.cpp b/bench/Matrix44Bench.cpp
index c369288..b79233c 100644
--- a/bench/Matrix44Bench.cpp
+++ b/bench/Matrix44Bench.cpp
@@ -12,7 +12,6 @@
 
 class Matrix44Bench : public SkBenchmark {
     SkString    fName;
-    enum { N = 10000 };
 public:
     Matrix44Bench(void* param, const char name[]) : INHERITED(param) {
         fName.printf("matrix44_%s", name);
@@ -29,8 +28,7 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        int n = SkBENCHLOOP(N * this->mulLoopCount());
-        for (int i = 0; i < n; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             this->performTest();
         }
     }
diff --git a/bench/MatrixBench.cpp b/bench/MatrixBench.cpp
index 8a5c5c6..c2cc5a2 100644
--- a/bench/MatrixBench.cpp
+++ b/bench/MatrixBench.cpp
@@ -13,7 +13,6 @@
 
 class MatrixBench : public SkBenchmark {
     SkString    fName;
-    enum { N = 100000 };
 public:
     MatrixBench(void* param, const char name[]) : INHERITED(param) {
         fName.printf("matrix_%s", name);
@@ -30,8 +29,7 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        int n = SkBENCHLOOP(N * this->mulLoopCount());
-        for (int i = 0; i < n; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             this->performTest();
         }
     }
@@ -297,11 +295,11 @@
     }
  private:
     enum {
-        kCount = SkBENCHLOOP(16)
+        kCount = 16
     };
     SkMatrix fMatrix;
-    SkPoint fSrc [16];
-    SkPoint fDst [16];
+    SkPoint fSrc [kCount];
+    SkPoint fDst [kCount];
     SkRandom fRandom;
     typedef MatrixBench INHERITED;
 };
@@ -337,11 +335,11 @@
     }
  private:
     enum {
-        kCount = SkBENCHLOOP(16)
+        kCount = 16
     };
     double fMatrix [9];
-    SkPoint fSrc [16];
-    SkPoint fDst [16];
+    SkPoint fSrc [kCount];
+    SkPoint fDst [kCount];
     SkRandom fRandom;
     typedef MatrixBench INHERITED;
 };
diff --git a/bench/MatrixConvolutionBench.cpp b/bench/MatrixConvolutionBench.cpp
index 161fc23..db25d99 100644
--- a/bench/MatrixConvolutionBench.cpp
+++ b/bench/MatrixConvolutionBench.cpp
@@ -40,7 +40,7 @@
         this->setupPaint(&paint);
         paint.setAntiAlias(true);
         SkRandom rand;
-        for (int i = 0; i < SkBENCHLOOP(3); i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400,
                                       rand.nextUScalar1() * 400);
             paint.setImageFilter(fFilter);
diff --git a/bench/MemoryBench.cpp b/bench/MemoryBench.cpp
index 3dff98f..ae14dac 100644
--- a/bench/MemoryBench.cpp
+++ b/bench/MemoryBench.cpp
@@ -15,10 +15,6 @@
 class ChunkAllocBench : public SkBenchmark {
     SkString    fName;
     size_t      fMinSize;
-
-    enum {
-        N = SkBENCHLOOP(1000)
-    };
 public:
     ChunkAllocBench(void* param, size_t minSize) : INHERITED(param) {
         fMinSize = minSize;
@@ -38,7 +34,7 @@
 
         SkChunkAlloc alloc(fMinSize);
 
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             size_t size = 0;
             int calls = 0;
             while (size < total) {
diff --git a/bench/MemsetBench.cpp b/bench/MemsetBench.cpp
index 660c8c3..efbfa1f 100644
--- a/bench/MemsetBench.cpp
+++ b/bench/MemsetBench.cpp
@@ -17,7 +17,6 @@
     size_t      fMinSize;
     size_t      fMaxSize;
     enum {
-        kLoop = 100,
         kBufferSize = 10000,
         VALUE32 = 0x12345678,
         VALUE16 = 0x1234
@@ -46,7 +45,7 @@
     }
 
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
-        for (int i = 0; i < kLoop; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             this->performTest();
         }
     }
diff --git a/bench/MergeBench.cpp b/bench/MergeBench.cpp
index 992507d..98a918a 100644
--- a/bench/MergeBench.cpp
+++ b/bench/MergeBench.cpp
@@ -38,7 +38,9 @@
                               SkRect::MakeWH(FILTER_WIDTH_LARGE, FILTER_HEIGHT_LARGE);
         SkPaint paint;
         paint.setImageFilter(mergeBitmaps())->unref();
-        canvas->drawRect(r, paint);
+        for (int i = 0; i < this->getLoops(); i++) {
+            canvas->drawRect(r, paint);
+        }
     }
 
 private:
diff --git a/bench/MorphologyBench.cpp b/bench/MorphologyBench.cpp
index f9657ba..2d4b4ee 100644
--- a/bench/MorphologyBench.cpp
+++ b/bench/MorphologyBench.cpp
@@ -60,7 +60,7 @@
         paint.setAntiAlias(true);
 
         SkRandom rand;
-        for (int i = 0; i < SkBENCHLOOP(3); i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400,
                                       rand.nextUScalar1() * 400);
             r.offset(fRadius, fRadius);
diff --git a/bench/MutexBench.cpp b/bench/MutexBench.cpp
index d96f3f6..5a7058d 100644
--- a/bench/MutexBench.cpp
+++ b/bench/MutexBench.cpp
@@ -8,10 +8,6 @@
 #include "SkThread.h"
 
 class MutexBench : public SkBenchmark {
-    enum {
-        N = SkBENCHLOOP(80),
-        M = SkBENCHLOOP(200)
-    };
 public:
     MutexBench(void* param) : INHERITED(param) {
         fIsRendering = false;
@@ -22,12 +18,10 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        for (int i = 0; i < N; i++) {
-            SK_DECLARE_STATIC_MUTEX(mu);
-            for (int j = 0; j < M; j++) {
-                mu.acquire();
-                mu.release();
-            }
+        SK_DECLARE_STATIC_MUTEX(mu);
+        for (int i = 0; i < this->getLoops(); i++) {
+            mu.acquire();
+            mu.release();
         }
     }
 
diff --git a/bench/PathBench.cpp b/bench/PathBench.cpp
index 057a2b0..37b47dd 100644
--- a/bench/PathBench.cpp
+++ b/bench/PathBench.cpp
@@ -29,7 +29,6 @@
     SkPaint     fPaint;
     SkString    fName;
     Flags       fFlags;
-    enum { N = SkBENCHLOOP(1000) };
 public:
     PathBench(void* param, Flags flags) : INHERITED(param), fFlags(flags) {
         fPaint.setStyle(flags & kStroke_Flag ? SkPaint::kStroke_Style :
@@ -63,7 +62,7 @@
             path.transform(m);
         }
 
-        int count = N;
+        int count = this->getLoops();
         if (fFlags & kBig_Flag) {
             count >>= 2;
         }
@@ -326,8 +325,6 @@
     }
 
 protected:
-    enum { N = SkBENCHLOOP(5000) };
-
     virtual const char* onGetName() SK_OVERRIDE {
         return "path_create";
     }
@@ -338,7 +335,7 @@
     }
 
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             this->makePath(&fPaths[i & (kPathCnt - 1)]);
         }
         this->restartMakingPaths();
@@ -365,8 +362,6 @@
     }
 
 protected:
-    enum { N = SkBENCHLOOP(30000) };
-
     virtual const char* onGetName() SK_OVERRIDE {
         return "path_copy";
     }
@@ -380,7 +375,7 @@
         this->finishedMakingPaths();
     }
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             int idx = i & (kPathCnt - 1);
             fCopies[idx] = fPaths[idx];
         }
@@ -409,8 +404,6 @@
     }
 
 protected:
-    enum { N = SkBENCHLOOP(30000) };
-
     virtual const char* onGetName() SK_OVERRIDE {
         return fInPlace ? "path_transform_in_place" : "path_transform_copy";
     }
@@ -430,11 +423,11 @@
 
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
         if (fInPlace) {
-            for (int i = 0; i < N; ++i) {
+            for (int i = 0; i < this->getLoops(); ++i) {
                 fPaths[i & (kPathCnt - 1)].transform(fMatrix);
             }
         } else {
-            for (int i = 0; i < N; ++i) {
+            for (int i = 0; i < this->getLoops(); ++i) {
                 int idx = i & (kPathCnt - 1);
                 fPaths[idx].transform(fMatrix, &fTransformed[idx]);
             }
@@ -466,8 +459,6 @@
     }
 
 protected:
-    enum { N = SkBENCHLOOP(40000) };
-
     virtual const char* onGetName() SK_OVERRIDE {
         return "path_equality_50%";
     }
@@ -485,7 +476,7 @@
     }
 
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             int idx = i & (kPathCnt - 1);
             fParity ^= (fPaths[idx] == fCopies[idx & ~0x1]);
         }
@@ -525,8 +516,6 @@
     }
 
 protected:
-    enum { N = SkBENCHLOOP(15000) };
-
     virtual const char* onGetName() SK_OVERRIDE {
         switch (fType) {
             case kAdd_AddType:
@@ -564,42 +553,42 @@
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
         switch (fType) {
             case kAdd_AddType:
-                for (int i = 0; i < N; ++i) {
+                for (int i = 0; i < this->getLoops(); ++i) {
                     int idx = i & (kPathCnt - 1);
                     SkPath result = fPaths0[idx];
                     result.addPath(fPaths1[idx]);
                 }
                 break;
             case kAddTrans_AddType:
-                for (int i = 0; i < N; ++i) {
+                for (int i = 0; i < this->getLoops(); ++i) {
                     int idx = i & (kPathCnt - 1);
                     SkPath result = fPaths0[idx];
                     result.addPath(fPaths1[idx], 2 * SK_Scalar1, 5 * SK_Scalar1);
                 }
                 break;
             case kAddMatrix_AddType:
-                for (int i = 0; i < N; ++i) {
+                for (int i = 0; i < this->getLoops(); ++i) {
                     int idx = i & (kPathCnt - 1);
                     SkPath result = fPaths0[idx];
                     result.addPath(fPaths1[idx], fMatrix);
                 }
                 break;
             case kPathTo_AddType:
-                for (int i = 0; i < N; ++i) {
+                for (int i = 0; i < this->getLoops(); ++i) {
                     int idx = i & (kPathCnt - 1);
                     SkPath result = fPaths0[idx];
                     result.pathTo(fPaths1[idx]);
                 }
                 break;
             case kReverseAdd_AddType:
-                for (int i = 0; i < N; ++i) {
+                for (int i = 0; i < this->getLoops(); ++i) {
                     int idx = i & (kPathCnt - 1);
                     SkPath result = fPaths0[idx];
                     result.reverseAddPath(fPaths1[idx]);
                 }
                 break;
             case kReversePathTo_AddType:
-                for (int i = 0; i < N; ++i) {
+                for (int i = 0; i < this->getLoops(); ++i) {
                     int idx = i & (kPathCnt - 1);
                     SkPath result = fPaths0[idx];
                     result.reversePathTo(fPaths1[idx]);
@@ -631,9 +620,6 @@
     SkString            fName;
     Flags               fFlags;
 
-    enum {
-        N = SkBENCHLOOP(100)
-    };
 public:
     CirclesBench(void* param, Flags flags) : INHERITED(param), fFlags(flags) {
         fName.printf("circles_%s", fFlags & kStroke_Flag ? "stroke" : "fill");
@@ -657,7 +643,7 @@
 
         SkRect r;
 
-        for (int i = 0; i < 5000; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkScalar radius = rand.nextUScalar1() * 3;
             r.fLeft = rand.nextUScalar1() * 300;
             r.fTop =  rand.nextUScalar1() * 300;
@@ -694,9 +680,6 @@
 protected:
     SkString            fName;
 
-    enum {
-        N = SkBENCHLOOP(100)
-    };
 public:
     ArbRoundRectBench(void* param, bool zeroRad) : INHERITED(param), fZeroRad(zeroRad) {
         if (zeroRad) {
@@ -757,7 +740,7 @@
         SkRandom rand;
         SkRect r;
 
-        for (int i = 0; i < 5000; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkPaint paint;
             paint.setColor(0xff000000 | rand.nextU());
             paint.setAntiAlias(true);
@@ -825,7 +808,7 @@
     }
 
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             const SkRect& rect = fQueryRects[i % kQueryRectCnt];
             fParity = fParity != fPath.conservativelyContainsRect(rect);
         }
@@ -852,7 +835,6 @@
     }
 
     enum {
-        N = SkBENCHLOOP(100000),
         kQueryRectCnt = 400,
     };
     static const SkRect kBounds;   // bounds for all random query rects
@@ -874,9 +856,6 @@
 #include "SkGeometry.h"
 
 class ConicBench_Chop5 : public SkBenchmark {
-    enum {
-        N = 100000
-    };
     SkConic fRQ;
 public:
     ConicBench_Chop5(void* param) : INHERITED(param) {
@@ -893,7 +872,7 @@
 
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
         SkConic dst[2];
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             fRQ.chopAt(0.5f, dst);
         }
     }
@@ -902,9 +881,6 @@
 };
 
 class ConicBench_ChopHalf : public SkBenchmark {
-    enum {
-        N = 100000
-    };
     SkConic fRQ;
 public:
     ConicBench_ChopHalf(void* param) : INHERITED(param) {
@@ -921,7 +897,7 @@
 
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
         SkConic dst[2];
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             fRQ.chop(dst);
         }
     }
@@ -954,7 +930,6 @@
 
 protected:
     enum {
-        N = 20000,
         CONICS = 100
     };
     SkConic fConics[CONICS];
@@ -974,7 +949,7 @@
 
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
         SkVector err;
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             for (int j = 0; j < CONICS; ++j) {
                 fConics[j].computeAsQuadError(&err);
             }
@@ -995,7 +970,7 @@
     }
 
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             for (int j = 0; j < CONICS; ++j) {
                 fConics[j].asQuadTol(SK_ScalarHalf);
             }
@@ -1016,7 +991,7 @@
     }
 
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             for (int j = 0; j < CONICS; ++j) {
                 fConics[j].computeQuadPOW2(SK_ScalarHalf);
             }
diff --git a/bench/PathIterBench.cpp b/bench/PathIterBench.cpp
index 987a752..c5ac7e4 100644
--- a/bench/PathIterBench.cpp
+++ b/bench/PathIterBench.cpp
@@ -30,8 +30,6 @@
     SkPath      fPath;
     bool        fRaw;
 
-    enum { N = SkBENCHLOOP(500) };
-
 public:
     PathIterBench(void* param, bool raw) : INHERITED(param) {
         fName.printf("pathiter_%s", raw ? "raw" : "consume");
@@ -67,7 +65,7 @@
 
     virtual void onDraw(SkCanvas*) SK_OVERRIDE {
         if (fRaw) {
-            for (int i = 0; i < N; ++i) {
+            for (int i = 0; i < this->getLoops(); ++i) {
                 SkPath::RawIter iter(fPath);
                 SkPath::Verb verb;
                 SkPoint      pts[4];
@@ -75,7 +73,7 @@
                 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { }
             }
         } else {
-            for (int i = 0; i < N; ++i) {
+            for (int i = 0; i < this->getLoops(); ++i) {
                 SkPath::Iter iter(fPath, false);
                 SkPath::Verb verb;
                 SkPoint      pts[4];
diff --git a/bench/PathUtilsBench.cpp b/bench/PathUtilsBench.cpp
index 613d49a..c3640f7 100644
--- a/bench/PathUtilsBench.cpp
+++ b/bench/PathUtilsBench.cpp
@@ -41,8 +41,6 @@
     SkString fName;
     char* bits[H * STRIDE];
 
-    enum { N = SkBENCHLOOP(20) };
-
 public:
     PathUtilsBench(void* param, Proc proc, const char name[]) : INHERITED(param) {
         fProc = proc;
@@ -56,7 +54,7 @@
 
     virtual void onDraw(SkCanvas* canvas) {
 
-        for (int i = 0; i < N; ++i){
+        for (int i = 0; i < this->getLoops(); ++i){
             //create a random 16x16 bitmap
             fillRandomBits(H * STRIDE, (char*) &bits);
 
diff --git a/bench/PerlinNoiseBench.cpp b/bench/PerlinNoiseBench.cpp
index d151825..605acf4 100644
--- a/bench/PerlinNoiseBench.cpp
+++ b/bench/PerlinNoiseBench.cpp
@@ -48,7 +48,10 @@
                                                  seed, stitchTiles ? &fSize : NULL);
         SkPaint paint;
         paint.setShader(shader)->unref();
-        this->drawClippedRect(canvas, x, y, paint);
+
+        for (int i = 0; i < this->getLoops(); i++) {
+            this->drawClippedRect(canvas, x, y, paint);
+        }
     }
 
     typedef SkBenchmark INHERITED;
diff --git a/bench/PicturePlaybackBench.cpp b/bench/PicturePlaybackBench.cpp
index bd84baf..7f8fe6f 100644
--- a/bench/PicturePlaybackBench.cpp
+++ b/bench/PicturePlaybackBench.cpp
@@ -26,7 +26,6 @@
     }
 
     enum {
-        N = SkBENCHLOOP(200),   // number of times to playback the picture
         PICTURE_WIDTH = 1000,
         PICTURE_HEIGHT = 4000,
         TEXT_SIZE = 10
@@ -44,16 +43,16 @@
         recordCanvas(pCanvas);
         picture.endRecording();
 
-        const SkPoint translateDelta = getTranslateDelta();
+        const SkPoint translateDelta = getTranslateDelta(this->getLoops());
 
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             picture.draw(canvas);
             canvas->translate(translateDelta.fX, translateDelta.fY);
         }
     }
 
     virtual void recordCanvas(SkCanvas* canvas) = 0;
-    virtual SkPoint getTranslateDelta() {
+    virtual SkPoint getTranslateDelta(int N) {
         SkIPoint canvasSize = onGetSize();
         return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/N),
                              SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/N));
diff --git a/bench/PictureRecordBench.cpp b/bench/PictureRecordBench.cpp
index f23f0cb..cbfad38 100644
--- a/bench/PictureRecordBench.cpp
+++ b/bench/PictureRecordBench.cpp
@@ -24,7 +24,6 @@
     }
 
     enum {
-        N = SkBENCHLOOP(25), // number of times to create the picture
         PICTURE_WIDTH = 1000,
         PICTURE_HEIGHT = 4000,
     };
@@ -34,25 +33,18 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        int n = (int)(N * this->innerLoopScale());
-        n = SkMax32(1, n);
+        SkPicture picture;
 
-        for (int i = 0; i < n; i++) {
+        SkCanvas* pCanvas = picture.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
+        recordCanvas(pCanvas);
 
-            SkPicture picture;
-
-            SkCanvas* pCanvas = picture.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
-            recordCanvas(pCanvas);
-
-            // we don't need to draw the picture as the endRecording step will
-            // do the work of transferring the recorded content into a playback
-            // object.
-            picture.endRecording();
-        }
+        // we don't need to draw the picture as the endRecording step will
+        // do the work of transferring the recorded content into a playback
+        // object.
+        picture.endRecording();
     }
 
     virtual void recordCanvas(SkCanvas* canvas) = 0;
-    virtual float innerLoopScale() const { return 1; }
 
     SkString fName;
     SkScalar fPictureWidth;
@@ -72,18 +64,15 @@
     DictionaryRecordBench(void* param)
         : INHERITED(param, "dictionaries") { }
 
-    enum {
-        M = SkBENCHLOOP(100),   // number of elements in each dictionary
-    };
 protected:
     virtual void recordCanvas(SkCanvas* canvas) {
 
-        const SkPoint translateDelta = getTranslateDelta();
+        const SkPoint translateDelta = getTranslateDelta(this->getLoops());
 
-        for (int i = 0; i < M; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
 
             SkColor color = SK_ColorYELLOW + (i % 255);
-            SkIRect rect = SkIRect::MakeWH(i,i);
+            SkIRect rect = SkIRect::MakeWH(i % PICTURE_WIDTH, i % PICTURE_HEIGHT);
 
             canvas->save();
 
@@ -119,7 +108,7 @@
         }
     }
 
-    SkPoint getTranslateDelta() {
+    SkPoint getTranslateDelta(int M) {
         SkIPoint canvasSize = onGetSize();
         return SkPoint::Make(SkIntToScalar((PICTURE_WIDTH - canvasSize.fX)/M),
                              SkIntToScalar((PICTURE_HEIGHT- canvasSize.fY)/M));
@@ -137,14 +126,10 @@
     UniquePaintDictionaryRecordBench(void* param)
         : INHERITED(param, "unique_paint_dictionary") { }
 
-    enum {
-        M = SkBENCHLOOP(15000),   // number of unique paint objects
-    };
 protected:
-    virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; }
     virtual void recordCanvas(SkCanvas* canvas) {
         SkRandom rand;
-        for (int i = 0; i < M; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkPaint paint;
             paint.setColor(rand.nextU());
             canvas->drawPaint(paint);
@@ -174,14 +159,12 @@
     }
 
     enum {
-        ObjCount = 100,           // number of unique paint objects
-        M = SkBENCHLOOP(50000),   // number of draw iterations
+        ObjCount = 100,  // number of unique paint objects
     };
 protected:
-    virtual float innerLoopScale() const SK_OVERRIDE { return 0.1f; }
     virtual void recordCanvas(SkCanvas* canvas) {
 
-        for (int i = 0; i < M; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             canvas->drawPaint(fPaint[i % ObjCount]);
         }
     }
diff --git a/bench/PremulAndUnpremulAlphaOpsBench.cpp b/bench/PremulAndUnpremulAlphaOpsBench.cpp
index f552097..eb494f4 100644
--- a/bench/PremulAndUnpremulAlphaOpsBench.cpp
+++ b/bench/PremulAndUnpremulAlphaOpsBench.cpp
@@ -46,8 +46,7 @@
         bmp2.setConfig(SkBitmap::kARGB_8888_Config, size.width(),
                        size.height());
 
-        static const int kLoopCount = SkBENCHLOOP(10);
-        for (int loop = 0; loop < kLoopCount; ++loop) {
+        for (int loop = 0; loop < this->getLoops(); ++loop) {
             // Unpremul -> Premul
             canvas->writePixels(bmp1, 0, 0, fUnPremulConfig);
             // Premul -> Unpremul
diff --git a/bench/RTreeBench.cpp b/bench/RTreeBench.cpp
index 7dc54ca..99f8ca8 100644
--- a/bench/RTreeBench.cpp
+++ b/bench/RTreeBench.cpp
@@ -16,7 +16,6 @@
 static const int GENERATE_EXTENTS = 1000;
 static const int NUM_BUILD_RECTS = 500;
 static const int NUM_QUERY_RECTS = 5000;
-static const int NUM_QUERIES = 1000;
 static const int GRID_WIDTH = 100;
 
 typedef SkIRect (*MakeRectProc)(SkRandom&, int, int);
@@ -47,7 +46,7 @@
     }
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
         SkRandom rand;
-        for (int i = 0; i < SkBENCHLOOP(100); ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             for (int j = 0; j < NUM_BUILD_RECTS; ++j) {
                 fTree->insert(reinterpret_cast<void*>(j), fProc(rand, j, NUM_BUILD_RECTS),
                               fBulkLoad);
@@ -98,16 +97,17 @@
     }
     virtual void onPreDraw() SK_OVERRIDE {
         SkRandom rand;
-        for (int j = 0; j < SkBENCHLOOP(NUM_QUERY_RECTS); ++j) {
-            fTree->insert(reinterpret_cast<void*>(j), fProc(rand, j,
-                           SkBENCHLOOP(NUM_QUERY_RECTS)), fBulkLoad);
+        for (int j = 0; j < NUM_QUERY_RECTS; ++j) {
+            fTree->insert(reinterpret_cast<void*>(j),
+                          fProc(rand, j, NUM_QUERY_RECTS),
+                          fBulkLoad);
         }
         fTree->flushDeferredInserts();
     }
 
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
         SkRandom rand;
-        for (int i = 0; i < SkBENCHLOOP(NUM_QUERIES); ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkTDArray<void*> hits;
             SkIRect query;
             switch(fQuery) {
diff --git a/bench/ReadPixBench.cpp b/bench/ReadPixBench.cpp
index 66db2eb..505ff32 100644
--- a/bench/ReadPixBench.cpp
+++ b/bench/ReadPixBench.cpp
@@ -45,9 +45,11 @@
 
         bitmap.setConfig(SkBitmap::kARGB_8888_Config, kWindowSize, kWindowSize);
 
-        for (int x = 0; x < kNumStepsX; ++x) {
-            for (int y = 0; y < kNumStepsY; ++y) {
-                canvas->readPixels(&bitmap, x * offX, y * offY);
+        for (int i = 0; i < this->getLoops(); i++) {
+            for (int x = 0; x < kNumStepsX; ++x) {
+                for (int y = 0; y < kNumStepsY; ++y) {
+                    canvas->readPixels(&bitmap, x * offX, y * offY);
+                }
             }
         }
     }
diff --git a/bench/RectBench.cpp b/bench/RectBench.cpp
index 99ff0a9..ebf270d 100644
--- a/bench/RectBench.cpp
+++ b/bench/RectBench.cpp
@@ -7,10 +7,13 @@
  */
 #include "SkBenchmark.h"
 #include "SkCanvas.h"
+#include "SkCommandLineFlags.h"
 #include "SkPaint.h"
 #include "SkRandom.h"
-#include "SkString.h"
 #include "SkShader.h"
+#include "SkString.h"
+
+DEFINE_double(strokeWidth, -1.0, "If set, use this stroke width in RectBench.");
 
 class RectBench : public SkBenchmark {
 public:
@@ -18,7 +21,7 @@
     enum {
         W = 640,
         H = 480,
-        N = SkBENCHLOOP(300)
+        N = 300,
     };
     SkRect  fRects[N];
     SkColor fColors[N];
@@ -66,10 +69,10 @@
             paint.setStyle(SkPaint::kStroke_Style);
             paint.setStrokeWidth(SkIntToScalar(fStroke));
         }
-        for (int i = 0; i < N; i++) {
-            paint.setColor(fColors[i]);
+        for (int i = 0; i < this->getLoops(); i++) {
+            paint.setColor(fColors[i % N]);
             this->setupPaint(&paint);
-            this->drawThisRect(canvas, fRects[i], paint);
+            this->drawThisRect(canvas, fRects[i % N], paint);
         }
     }
 private:
@@ -144,19 +147,21 @@
         };
         size_t sizes = SK_ARRAY_COUNT(gSizes);
 
-        if (this->hasStrokeWidth()) {
-            gSizes[0] = this->getStrokeWidth();
+        if (FLAGS_strokeWidth >= 0) {
+            gSizes[0] = FLAGS_strokeWidth;
             sizes = 1;
         }
 
         SkPaint paint;
         paint.setStrokeCap(SkPaint::kRound_Cap);
 
-        for (size_t i = 0; i < sizes; i++) {
-            paint.setStrokeWidth(gSizes[i]);
-            this->setupPaint(&paint);
-            canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint);
-            paint.setColor(fColors[i]);
+        for (int loop = 0; loop < this->getLoops(); loop++) {
+            for (size_t i = 0; i < sizes; i++) {
+                paint.setStrokeWidth(gSizes[i]);
+                this->setupPaint(&paint);
+                canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint);
+                paint.setColor(fColors[i % N]);
+            }
         }
     }
     virtual const char* onGetName() { return fName; }
@@ -190,21 +195,23 @@
         SkRect r = { -kHalfRectSize, -kHalfRectSize, kHalfRectSize, kHalfRectSize };
         int rot = 0;
 
-        // Draw small aa rects in a grid across the screen
-        for (SkScalar y = kHalfRectSize+SK_Scalar1; y < H; y += 2*kHalfRectSize+2) {
-            for (SkScalar x = kHalfRectSize+SK_Scalar1; x < W; x += 2*kHalfRectSize+2) {
-                canvas->save();
-                canvas->translate(x, y);
+        for (int i = 0; i < this->getLoops(); i++) {
+            // Draw small aa rects in a grid across the screen
+            for (SkScalar y = kHalfRectSize+SK_Scalar1; y < H; y += 2*kHalfRectSize+2) {
+                for (SkScalar x = kHalfRectSize+SK_Scalar1; x < W; x += 2*kHalfRectSize+2) {
+                    canvas->save();
+                    canvas->translate(x, y);
 
-                if (fRotate) {
-                    SkMatrix rotate;
-                    rotate.setRotate(SkIntToScalar(rot));
-                    canvas->concat(rotate);
-                    rot += 10;
+                    if (fRotate) {
+                        SkMatrix rotate;
+                        rotate.setRotate(SkIntToScalar(rot));
+                        canvas->concat(rotate);
+                        rot += 10;
+                    }
+
+                    canvas->drawRect(r, paint);
+                    canvas->restore();
                 }
-
-                canvas->drawRect(r, paint);
-                canvas->restore();
             }
         }
 
@@ -242,8 +249,8 @@
         };
         size_t sizes = SK_ARRAY_COUNT(gSizes);
 
-        if (this->hasStrokeWidth()) {
-            gSizes[0] = this->getStrokeWidth();
+        if (FLAGS_strokeWidth >= 0) {
+            gSizes[0] = FLAGS_strokeWidth;
             sizes = 1;
         }
         SkRandom rand;
@@ -262,29 +269,31 @@
                                               SkShader::kClamp_TileMode);
             paint.setShader(s)->unref();
         }
-        for (size_t i = 0; i < sizes; i++) {
-            switch (_type) {
-                case kMaskOpaque:
-                    color = fColors[i];
-                    alpha = 0xFF;
-                    break;
-                case kMaskBlack:
-                    alpha = 0xFF;
-                    color = 0xFF000000;
-                    break;
-                case kMaskColor:
-                    color = fColors[i];
-                    alpha = rand.nextU() & 255;
-                    break;
-                case KMaskShader:
-                    break;
-            }
-            paint.setStrokeWidth(gSizes[i]);
-            this->setupPaint(&paint);
-            paint.setColor(color);
-            paint.setAlpha(alpha);
-            canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint);
-       }
+        for (int loop = 0; loop < this->getLoops(); loop++) {
+            for (size_t i = 0; i < sizes; i++) {
+                switch (_type) {
+                    case kMaskOpaque:
+                        color = fColors[i];
+                        alpha = 0xFF;
+                        break;
+                    case kMaskBlack:
+                        alpha = 0xFF;
+                        color = 0xFF000000;
+                        break;
+                    case kMaskColor:
+                        color = fColors[i];
+                        alpha = rand.nextU() & 255;
+                        break;
+                    case KMaskShader:
+                        break;
+                }
+                paint.setStrokeWidth(gSizes[i]);
+                this->setupPaint(&paint);
+                paint.setColor(color);
+                paint.setAlpha(alpha);
+                canvas->drawPoints(fMode, N * 2, SkTCast<SkPoint*>(fRects), paint);
+           }
+        }
     }
     virtual const char* onGetName() { return fName; }
 private:
diff --git a/bench/RectoriBench.cpp b/bench/RectoriBench.cpp
index bb88797..0a0b71d 100644
--- a/bench/RectoriBench.cpp
+++ b/bench/RectoriBench.cpp
@@ -27,7 +27,7 @@
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
         SkRandom Random;
 
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkScalar blurSigma = Random.nextRangeScalar(1.5f, 25.0f);
             SkScalar size = Random.nextRangeScalar(20*blurSigma, 50*blurSigma);
 
@@ -70,8 +70,6 @@
         H = 480,
     };
 
-    enum { N = SkBENCHLOOP(100) };
-
     SkLayerDrawLooper* createLooper(SkScalar xOff, SkScalar sigma) {
         SkLayerDrawLooper* looper = new SkLayerDrawLooper;
 
diff --git a/bench/RefCntBench.cpp b/bench/RefCntBench.cpp
index 26c98b9..2cc7688 100644
--- a/bench/RefCntBench.cpp
+++ b/bench/RefCntBench.cpp
@@ -11,8 +11,7 @@
 #include <memory>
 
 enum {
-    N = SkBENCHLOOP(100000),
-    M = SkBENCHLOOP(2)
+    M = 2
 };
 
 class RefCntBench_Stack : public SkBenchmark {
@@ -26,7 +25,7 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkRefCnt ref;
             for (int j = 0; j < M; ++j) {
                 ref.ref();
@@ -64,7 +63,7 @@
 
     virtual void onDraw(SkCanvas*) {
         char memory[sizeof(PlacedRefCnt)];
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             PlacedRefCnt* ref = new (memory) PlacedRefCnt();
             for (int j = 0; j < M; ++j) {
                 ref->ref();
@@ -89,7 +88,7 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkRefCnt* ref = new SkRefCnt();
             for (int j = 0; j < M; ++j) {
                 ref->ref();
@@ -116,7 +115,7 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkWeakRefCnt ref;
             for (int j = 0; j < M; ++j) {
                 ref.ref();
@@ -147,7 +146,7 @@
 
     virtual void onDraw(SkCanvas*) {
         char memory[sizeof(PlacedWeakRefCnt)];
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             PlacedWeakRefCnt* ref = new (memory) PlacedWeakRefCnt();
             for (int j = 0; j < M; ++j) {
                 ref->ref();
@@ -172,7 +171,7 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkWeakRefCnt* ref = new SkWeakRefCnt();
             for (int j = 0; j < M; ++j) {
                 ref->ref();
diff --git a/bench/RegionBench.cpp b/bench/RegionBench.cpp
index 7a306e9..ffd674a 100644
--- a/bench/RegionBench.cpp
+++ b/bench/RegionBench.cpp
@@ -74,12 +74,10 @@
     SkRegion fA, fB;
     Proc     fProc;
     SkString fName;
-    int      fLoopMul;
 
     enum {
         W = 1024,
         H = 768,
-        N = SkBENCHLOOP(2000)
     };
 
     SkIRect randrect(SkRandom& rand) {
@@ -90,10 +88,9 @@
         return SkIRect::MakeXYWH(x, y, w >> 1, h >> 1);
     }
 
-    RegionBench(void* param, int count, Proc proc, const char name[], int mul = 1) : INHERITED(param) {
+    RegionBench(void* param, int count, Proc proc, const char name[]) : INHERITED(param) {
         fProc = proc;
         fName.printf("region_%s_%d", name, count);
-        fLoopMul = mul;
 
         SkRandom rand;
         for (int i = 0; i < count; i++) {
@@ -108,8 +105,7 @@
 
     virtual void onDraw(SkCanvas* canvas) {
         Proc proc = fProc;
-        int n = fLoopMul * N;
-        for (int i = 0; i < n; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             proc(fA, fB);
         }
     }
@@ -125,9 +121,9 @@
 static SkBenchmark* gF2(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, diff_proc, "difference")); }
 static SkBenchmark* gF3(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, diffrect_proc, "differencerect")); }
 static SkBenchmark* gF4(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, diffrectbig_proc, "differencerectbig")); }
-static SkBenchmark* gF5(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, containsrect_proc, "containsrect", 100)); }
-static SkBenchmark* gF6(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, sectsrgn_proc, "intersectsrgn", 10)); }
-static SkBenchmark* gF7(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, sectsrect_proc, "intersectsrect", 200)); }
+static SkBenchmark* gF5(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, containsrect_proc, "containsrect")); }
+static SkBenchmark* gF6(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, sectsrgn_proc, "intersectsrgn")); }
+static SkBenchmark* gF7(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, sectsrect_proc, "intersectsrect")); }
 static SkBenchmark* gF8(void* p) { return SkNEW_ARGS(RegionBench, (p, SMALL, containsxy_proc, "containsxy")); }
 
 static BenchRegistry gR0(gF0);
diff --git a/bench/RegionContainBench.cpp b/bench/RegionContainBench.cpp
index 8668513..c4cbc94 100644
--- a/bench/RegionContainBench.cpp
+++ b/bench/RegionContainBench.cpp
@@ -26,7 +26,6 @@
         W = 200,
         H = 200,
         COUNT = 10,
-        N = SkBENCHLOOP(20000)
     };
 
     SkIRect randrect(SkRandom& rand, int i) {
@@ -54,7 +53,7 @@
     virtual void onDraw(SkCanvas*) {
         Proc proc = fProc;
 
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
            proc(fA, fB);
         }
     }
diff --git a/bench/RepeatTileBench.cpp b/bench/RepeatTileBench.cpp
index 348f906..ab7ccf4 100644
--- a/bench/RepeatTileBench.cpp
+++ b/bench/RepeatTileBench.cpp
@@ -89,7 +89,6 @@
     SkBitmap         fBitmap;
     bool             fIsOpaque;
     SkBitmap::Config fConfig;
-    enum { N = SkBENCHLOOP(20) };
 public:
     RepeatTileBench(void* param, SkBitmap::Config c, bool isOpaque = false) : INHERITED(param) {
         const int w = 50;
@@ -135,7 +134,7 @@
         SkPaint paint(fPaint);
         this->setupPaint(&paint);
 
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             canvas->drawPaint(paint);
         }
     }
diff --git a/bench/ScalarBench.cpp b/bench/ScalarBench.cpp
index 333dd22..b1014f4 100644
--- a/bench/ScalarBench.cpp
+++ b/bench/ScalarBench.cpp
@@ -13,7 +13,6 @@
 
 class ScalarBench : public SkBenchmark {
     SkString    fName;
-    enum { N = 100000 };
 public:
     ScalarBench(void* param, const char name[]) : INHERITED(param) {
         fName.printf("scalar_%s", name);
@@ -30,8 +29,7 @@
     }
 
     virtual void onDraw(SkCanvas* canvas) {
-        int n = SkBENCHLOOP(N * this->mulLoopCount());
-        for (int i = 0; i < n; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             this->performTest();
         }
     }
@@ -135,7 +133,6 @@
 class RectBoundsBench : public SkBenchmark {
     enum {
         PTS = 100,
-        N = SkBENCHLOOP(10000)
     };
     SkPoint fPts[PTS];
 
@@ -156,7 +153,7 @@
 
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
         SkRect r;
-        for (int i = 0; i < N; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             r.set(fPts, PTS);
         }
     }
diff --git a/bench/ShaderMaskBench.cpp b/bench/ShaderMaskBench.cpp
index 0e8e4bb..2738cff 100644
--- a/bench/ShaderMaskBench.cpp
+++ b/bench/ShaderMaskBench.cpp
@@ -37,7 +37,6 @@
     SkString    fText;
     SkString    fName;
     FontQuality fFQ;
-    enum { N = SkBENCHLOOP(500) };
 public:
     ShaderMaskBench(void* param, bool isOpaque, FontQuality fq) : INHERITED(param) {
         fFQ = fq;
@@ -72,14 +71,14 @@
         const SkScalar y0 = SkIntToScalar(-10);
 
         paint.setTextSize(SkIntToScalar(12));
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
             SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
             canvas->drawText(fText.c_str(), fText.size(), x, y, paint);
         }
 
         paint.setTextSize(SkIntToScalar(48));
-        for (int i = 0; i < N/4; i++) {
+        for (int i = 0; i < this->getLoops() / 4 ; i++) {
             SkScalar x = x0 + rand.nextUScalar1() * dim.fX;
             SkScalar y = y0 + rand.nextUScalar1() * dim.fY;
             canvas->drawText(fText.c_str(), fText.size(), x, y, paint);
diff --git a/bench/SkBenchmark.cpp b/bench/SkBenchmark.cpp
index 43f78b0..09e109e 100644
--- a/bench/SkBenchmark.cpp
+++ b/bench/SkBenchmark.cpp
@@ -9,18 +9,19 @@
 #include "SkPaint.h"
 #include "SkParse.h"
 
+const char* SkTriState::Name[] = { "default", "true", "false" };
+
 SK_DEFINE_INST_COUNT(SkBenchmark)
 
 template BenchRegistry* BenchRegistry::gHead;
 
-SkBenchmark::SkBenchmark(void* defineDict) {
-    fDict = reinterpret_cast<const SkTDict<const char*>*>(defineDict);
+SkBenchmark::SkBenchmark(void* /*ignored*/) {
     fForceAlpha = 0xFF;
     fForceAA = true;
     fDither = SkTriState::kDefault;
-    fHasStrokeWidth = false;
     fIsRendering = true;
     fOrMask = fClearMask = 0;
+    fLoops = 1;
 }
 
 const char* SkBenchmark::getName() {
@@ -55,33 +56,6 @@
     }
 }
 
-const char* SkBenchmark::findDefine(const char* key) const {
-    if (fDict) {
-        const char* value;
-        if (fDict->find(key, &value)) {
-            return value;
-        }
-    }
-    return NULL;
-}
-
-bool SkBenchmark::findDefine32(const char* key, int32_t* value) const {
-    const char* valueStr = this->findDefine(key);
-    if (valueStr) {
-        SkParse::FindS32(valueStr, value);
-        return true;
-    }
-    return false;
-}
-
-bool SkBenchmark::findDefineScalar(const char* key, SkScalar* value) const {
-    const char* valueStr = this->findDefine(key);
-    if (valueStr) {
-        SkParse::FindScalar(valueStr, value);
-        return true;
-    }
-    return false;
-}
 
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/bench/SkBenchmark.h b/bench/SkBenchmark.h
index 7ebe104..343bde2 100644
--- a/bench/SkBenchmark.h
+++ b/bench/SkBenchmark.h
@@ -10,7 +10,6 @@
 
 #include "SkRefCnt.h"
 #include "SkPoint.h"
-#include "SkTDict.h"
 #include "SkTRegistry.h"
 
 #define DEF_BENCH(code) \
@@ -27,12 +26,6 @@
  */
 
 
-#ifdef SK_DEBUG
-    #define SkBENCHLOOP(n) 1
-#else
-    #define SkBENCHLOOP(n) n
-#endif
-
 class SkCanvas;
 class SkPaint;
 
@@ -43,6 +36,7 @@
         kTrue,
         kFalse
     };
+    static const char* Name[];
 };
 
 class SkBenchmark : public SkRefCnt {
@@ -82,19 +76,6 @@
         fDither = state;
     }
 
-    void setStrokeWidth(SkScalar width) {
-      strokeWidth = width;
-      fHasStrokeWidth = true;
-    }
-
-    SkScalar getStrokeWidth() {
-      return strokeWidth;
-    }
-
-    bool hasStrokeWidth() {
-      return fHasStrokeWidth;
-    }
-
     /** If true; the benchmark does rendering; if false, the benchmark
         doesn't, and so need not be re-run in every different rendering
         mode. */
@@ -102,10 +83,6 @@
         return fIsRendering;
     }
 
-    const char* findDefine(const char* key) const;
-    bool findDefine32(const char* key, int32_t* value) const;
-    bool findDefineScalar(const char* key, SkScalar* value) const;
-
     /** Assign masks for paint-flags. These will be applied when setupPaint()
      *  is called.
      *
@@ -120,7 +97,14 @@
         fClearMask = clearMask;
     }
 
-    float getDurationScale() { return this->onGetDurationScale(); }
+    // The bench framework calls this to control the runtime of a bench.
+    void setLoops(int loops) {
+        fLoops = loops;
+    }
+
+    // Each bench should do its main work in a loop like this:
+    //   for (int i = 0; i < this->getLoops(); i++) { <work here> }
+    int getLoops() const { return fLoops; }
 
 protected:
     virtual void setupPaint(SkPaint* paint);
@@ -129,27 +113,18 @@
     virtual void onPreDraw() {}
     virtual void onDraw(SkCanvas*) = 0;
     virtual void onPostDraw() {}
-    // the caller will scale the computed duration by this value. It allows a
-    // slow bench to run fewer inner loops, but return the corresponding scale
-    // so that its reported duration can be compared against other benches.
-    // e.g.
-    //      if I run 10x slower, I can run 1/10 the number of inner-loops, but
-    //      return 10.0 for my durationScale, so I "report" the honest duration.
-    virtual float onGetDurationScale() { return 1; }
 
     virtual SkIPoint onGetSize();
     /// Defaults to true.
     bool    fIsRendering;
 
 private:
-    const SkTDict<const char*>* fDict;
     int     fForceAlpha;
     bool    fForceAA;
     bool    fForceFilter;
     SkTriState::State  fDither;
-    bool    fHasStrokeWidth;
-    SkScalar strokeWidth;
     uint32_t    fOrMask, fClearMask;
+    int fLoops;
 
     typedef SkRefCnt INHERITED;
 };
diff --git a/bench/SortBench.cpp b/bench/SortBench.cpp
index c19ebae..279c8ad 100644
--- a/bench/SortBench.cpp
+++ b/bench/SortBench.cpp
@@ -121,8 +121,7 @@
     }
 
     virtual void onDraw(SkCanvas*) {
-        int n = SkBENCHLOOP(200);
-        for (int i = 0; i < n; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             memcpy(fSorted, fUnsorted, fCount * sizeof(int));
             fSortProc(fSorted, fCount);
 #ifdef SK_DEBUG
diff --git a/bench/StrokeBench.cpp b/bench/StrokeBench.cpp
index 15c9bef..33772dd 100644
--- a/bench/StrokeBench.cpp
+++ b/bench/StrokeBench.cpp
@@ -58,7 +58,6 @@
     SkPaint::Join fJoin;
     RRectRec fRec;
     DrawProc fProc;
-    enum { N = SkBENCHLOOP(500) };
 public:
     StrokeRRectBench(void* param, SkPaint::Join j, DrawProc proc) : SkBenchmark(param) {
         static const char* gJoinName[] = {
@@ -85,7 +84,7 @@
         fRec.fPaint.setStyle(SkPaint::kStroke_Style);
         fRec.fPaint.setStrokeJoin(fJoin);
         fRec.fPaint.setStrokeWidth(5);
-        fProc(&fRec, N);
+        fProc(&fRec, this->getLoops());
     }
 
 private:
diff --git a/bench/TableBench.cpp b/bench/TableBench.cpp
index e6efe25..8dcefbe 100644
--- a/bench/TableBench.cpp
+++ b/bench/TableBench.cpp
@@ -25,8 +25,6 @@
 // This trio of drawRects is then repeat for the next cell.
 class TableBench : public SkBenchmark {
 public:
-
-    static const int kNumIterations = SkBENCHLOOP(10);
     static const int kNumRows = 48;
     static const int kNumCols = 32;
 
@@ -40,14 +38,13 @@
     }
 
     virtual void onDraw(SkCanvas* canvas) {
-
         SkPaint cellPaint;
         cellPaint.setColor(0xFFFFFFF);
 
         SkPaint borderPaint;
         borderPaint.setColor(0xFFCCCCCC);
 
-        for (int i = 0; i < kNumIterations; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             for (int row = 0; row < kNumRows; ++row) {
                 for (int col = 0; col < kNumCols; ++col) {
                     SkRect cell = SkRect::MakeLTRB(col * kCellWidth,
diff --git a/bench/TextBench.cpp b/bench/TextBench.cpp
index 9334c33..7aac2c0 100644
--- a/bench/TextBench.cpp
+++ b/bench/TextBench.cpp
@@ -45,7 +45,6 @@
     FontQuality fFQ;
     bool        fDoPos;
     SkPoint*    fPos;
-    enum { N = SkBENCHLOOP(800) };
 public:
     TextBench(void* param, const char text[], int ps,
               SkColor color, FontQuality fq, bool doPos = false) : INHERITED(param) {
@@ -112,7 +111,7 @@
             canvas->translate(SK_Scalar1, SK_Scalar1);
         }
 
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             if (fDoPos) {
                 canvas->drawPosText(fText.c_str(), fText.size(), fPos, paint);
             } else {
diff --git a/bench/TileBench.cpp b/bench/TileBench.cpp
index 7f2e7a8..44235eb 100644
--- a/bench/TileBench.cpp
+++ b/bench/TileBench.cpp
@@ -34,7 +34,6 @@
     bool                fDoFilter;
     bool                fDoTrans;
     bool                fDoScale;
-    enum { N = SkBENCHLOOP(20) };
     static const int kWidth = 1;
     static const int kHeight = 300;
 
@@ -106,7 +105,7 @@
         SkPaint bgPaint;
         bgPaint.setColor(SK_ColorWHITE);
 
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             if (fDoTrans) {
                 canvas->drawRect(r, bgPaint);
             }
diff --git a/bench/VertBench.cpp b/bench/VertBench.cpp
index 5456e28..79dcc9ad 100644
--- a/bench/VertBench.cpp
+++ b/bench/VertBench.cpp
@@ -26,7 +26,6 @@
         COL = 20,
         PTS = (ROW + 1) * (COL + 1),
         IDX = ROW * COL * 6,
-        N = SkBENCHLOOP(10)
     };
 
     SkPoint fPts[PTS];
@@ -82,7 +81,7 @@
         SkPaint paint;
         this->setupPaint(&paint);
 
-        for (int i = 0; i < N; i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             canvas->drawVertices(SkCanvas::kTriangles_VertexMode, PTS,
                                  fPts, NULL, fColors, NULL, fIdx, IDX, paint);
         }
diff --git a/bench/WritePixelsBench.cpp b/bench/WritePixelsBench.cpp
index 7803a6d..a9b6763 100644
--- a/bench/WritePixelsBench.cpp
+++ b/bench/WritePixelsBench.cpp
@@ -56,14 +56,12 @@
         bmp.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
         canvas->readPixels(&bmp, 0, 0);
 
-        for (int loop = 0; loop < kLoopCount; ++loop) {
+        for (int loop = 0; loop < this->getLoops(); ++loop) {
             canvas->writePixels(bmp, 0, 0, fConfig);
         }
     }
 
 private:
-    static const int kLoopCount = SkBENCHLOOP(50);
-
     SkCanvas::Config8888 fConfig;
     SkString             fName;
 
diff --git a/bench/WriterBench.cpp b/bench/WriterBench.cpp
index 68c694e..948c0ad 100644
--- a/bench/WriterBench.cpp
+++ b/bench/WriterBench.cpp
@@ -25,7 +25,7 @@
         static const char gStr[] = "abcdefghimjklmnopqrstuvwxyz";
         static const size_t gLen = strlen(gStr);
         SkWriter32 writer(256 * 4);
-        for (int i = 0; i < SkBENCHLOOP(800); i++) {
+        for (int i = 0; i < this->getLoops(); i++) {
             for (size_t j = 0; j <= gLen; j++) {
                 writer.writeString(gStr, j);
             }
diff --git a/bench/XfermodeBench.cpp b/bench/XfermodeBench.cpp
index 0f70a4c..993fc8f 100644
--- a/bench/XfermodeBench.cpp
+++ b/bench/XfermodeBench.cpp
@@ -36,7 +36,7 @@
     virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
         SkISize size = canvas->getDeviceSize();
         SkRandom random;
-        for (int i = 0; i < kNumRects; ++i) {
+        for (int i = 0; i < this->getLoops(); ++i) {
             SkPaint paint;
             paint.setXfermode(fXfermode.get());
             paint.setColor(random.nextU());
@@ -54,7 +54,6 @@
 
 private:
     enum {
-        kNumRects = SkBENCHLOOP(75),
         kMinSize = 50,
         kMaxSize = 100,
     };
diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp
index 472d4b9..289d5cb 100644
--- a/bench/benchmain.cpp
+++ b/bench/benchmain.cpp
@@ -6,47 +6,37 @@
  * found in the LICENSE file.
  */
 
-
-#include "BenchTimer.h"
-
 #if SK_SUPPORT_GPU
 #include "GrContext.h"
 #include "GrContextFactory.h"
-#include "gl/GrGLDefines.h"
 #include "GrRenderTarget.h"
 #include "SkGpuDevice.h"
+#include "gl/GrGLDefines.h"
 #else
 class GrContext;
 #endif // SK_SUPPORT_GPU
 
+#include "BenchTimer.h"
 #include "SkBenchLogger.h"
 #include "SkBenchmark.h"
 #include "SkBitmapDevice.h"
 #include "SkCanvas.h"
 #include "SkCommandLineFlags.h"
 #include "SkDeferredCanvas.h"
-#include "SkColorPriv.h"
 #include "SkGraphics.h"
 #include "SkImageEncoder.h"
-#include "SkNWayCanvas.h"
+#include "SkOSFile.h"
 #include "SkPicture.h"
 #include "SkString.h"
-#include "SkTArray.h"
-#include "TimerData.h"
 
-enum benchModes {
-    kNormal_benchModes,
-    kDeferred_benchModes,
-    kDeferredSilent_benchModes,
-    kRecord_benchModes,
-    kPictureRecord_benchModes
+enum BenchMode {
+    kNormal_BenchMode,
+    kDeferred_BenchMode,
+    kDeferredSilent_BenchMode,
+    kRecord_BenchMode,
+    kPictureRecord_BenchMode
 };
-
-#ifdef SK_DEBUG
-static const bool kDebugOnly = true;
-#else
-static const bool kDebugOnly = false;
-#endif
+const char* BenchMode_Name[] = { "normal", "deferred", "deferredSilent", "record", "picturerecord" };
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -58,43 +48,21 @@
     }
 }
 
-#if 0
-static bool equal(const SkBitmap& bm1, const SkBitmap& bm2) {
-    if (bm1.width() != bm2.width() ||
-        bm1.height() != bm2.height() ||
-        bm1.config() != bm2.config()) {
-        return false;
-    }
-
-    size_t pixelBytes = bm1.width() * bm1.bytesPerPixel();
-    for (int y = 0; y < bm1.height(); y++) {
-        if (memcmp(bm1.getAddr(0, y), bm2.getAddr(0, y), pixelBytes)) {
-            return false;
-        }
-    }
-    return true;
-}
-#endif
-
 class Iter {
 public:
-    Iter(void* param) {
-        fBench = BenchRegistry::Head();
-        fParam = param;
-    }
+    Iter() : fBench(BenchRegistry::Head()) {}
 
     SkBenchmark* next() {
         if (fBench) {
             BenchRegistry::Factory f = fBench->factory();
             fBench = fBench->next();
-            return f(fParam);
+            return f(NULL);
         }
         return NULL;
     }
 
 private:
     const BenchRegistry* fBench;
-    void* fParam;
 };
 
 class AutoPrePostDraw {
@@ -144,13 +112,12 @@
         }
     }
 
-    SkString str;
-    make_filename(name, &str);
-    str.appendf("_%s.png", config);
-    str.prepend(dir);
-    ::remove(str.c_str());
-    SkImageEncoder::EncodeFile(str.c_str(), copy, SkImageEncoder::kPNG_Type,
-                               100);
+    SkString filename;
+    make_filename(name, &filename);
+    filename.appendf("_%s.png", config);
+    SkString path = SkOSPath::SkPathJoin(dir, filename.c_str());
+    ::remove(path.c_str());
+    SkImageEncoder::EncodeFile(path.c_str(), copy, SkImageEncoder::kPNG_Type, 100);
 }
 
 static void performClip(SkCanvas* canvas, int w, int h) {
@@ -184,14 +151,6 @@
     canvas->translate(-x, -y);
 }
 
-static bool parse_bool_arg(char * const* argv, char* const* stop, bool* var) {
-    if (argv < stop) {
-        *var = atoi(*argv) != 0;
-        return true;
-    }
-    return false;
-}
-
 enum Backend {
     kNonRendering_Backend,
     kRaster_Backend,
@@ -237,111 +196,82 @@
 #if SK_SUPPORT_GPU
 GrContextFactory gContextFactory;
 typedef GrContextFactory::GLContextType GLContextType;
-static const GLContextType kDontCareGLCtxType = GrContextFactory::kNative_GLContextType;
+static const GLContextType kNative = GrContextFactory::kNative_GLContextType;
+#if SK_ANGLE
+static const GLContextType kANGLE  = GrContextFactory::kANGLE_GLContextType;
+#else
+static const GLContextType kANGLE  = kNative;
+#endif
+static const GLContextType kDebug  = GrContextFactory::kDebug_GLContextType;
+static const GLContextType kNull   = GrContextFactory::kNull_GLContextType;
 #else
 typedef int GLContextType;
-static const GLContextType kDontCareGLCtxType = 0;
+static const GLContextType kNative = 0, kANGLE = 0, kDebug = 0, kNull = 0;
 #endif
 
-static const struct {
-    SkBitmap::Config    fConfig;
-    const char*         fName;
-    int                 fSampleCnt;
-    Backend             fBackend;
-    GLContextType       fContextType;
-    bool                fRunByDefault;
+#ifdef SK_DEBUG
+static const bool kIsDebug = true;
+#else
+static const bool kIsDebug = false;
+#endif
+
+static const struct Config {
+    SkBitmap::Config    config;
+    const char*         name;
+    int                 sampleCount;
+    Backend             backend;
+    GLContextType       contextType;
+    bool                runByDefault;
 } gConfigs[] = {
-    { SkBitmap::kNo_Config,         "NONRENDERING", 0, kNonRendering_Backend, kDontCareGLCtxType,                      true     },
-    { SkBitmap::kARGB_8888_Config,  "8888",         0, kRaster_Backend,       kDontCareGLCtxType,                      true     },
-    { SkBitmap::kRGB_565_Config,    "565",          0, kRaster_Backend,       kDontCareGLCtxType,                      true     },
+    { SkBitmap::kNo_Config,        "NONRENDERING", 0, kNonRendering_Backend, kNative, true},
+    { SkBitmap::kARGB_8888_Config, "8888",         0, kRaster_Backend,       kNative, true},
+    { SkBitmap::kRGB_565_Config,   "565",          0, kRaster_Backend,       kNative, true},
 #if SK_SUPPORT_GPU
-    { SkBitmap::kARGB_8888_Config,  "GPU",          0, kGPU_Backend,          GrContextFactory::kNative_GLContextType, true     },
-    { SkBitmap::kARGB_8888_Config,  "MSAA4",        4, kGPU_Backend,          GrContextFactory::kNative_GLContextType, false    },
-    { SkBitmap::kARGB_8888_Config,  "MSAA16",      16, kGPU_Backend,          GrContextFactory::kNative_GLContextType, false    },
+    { SkBitmap::kARGB_8888_Config, "GPU",          0, kGPU_Backend,          kNative, true},
+    { SkBitmap::kARGB_8888_Config, "MSAA4",        4, kGPU_Backend,          kNative, false},
+    { SkBitmap::kARGB_8888_Config, "MSAA16",      16, kGPU_Backend,          kNative, false},
 #if SK_ANGLE
-    { SkBitmap::kARGB_8888_Config,  "ANGLE",        0, kGPU_Backend,          GrContextFactory::kANGLE_GLContextType,  true     },
+    { SkBitmap::kARGB_8888_Config, "ANGLE",        0, kGPU_Backend,          kANGLE,  true},
 #endif // SK_ANGLE
-    { SkBitmap::kARGB_8888_Config,  "Debug",        0, kGPU_Backend,          GrContextFactory::kDebug_GLContextType,  kDebugOnly },
-    { SkBitmap::kARGB_8888_Config,  "NULLGPU",      0, kGPU_Backend,          GrContextFactory::kNull_GLContextType,   true     },
+    { SkBitmap::kARGB_8888_Config, "Debug",        0, kGPU_Backend,          kDebug,  kIsDebug},
+    { SkBitmap::kARGB_8888_Config, "NULLGPU",      0, kGPU_Backend,          kNull,   true},
 #endif // SK_SUPPORT_GPU
 };
 
-static int findConfig(const char config[]) {
-    for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); i++) {
-        if (!strcmp(config, gConfigs[i].fName)) {
-            return i;
-        }
-    }
-    return -1;
-}
+DEFINE_string(outDir, "", "If given, image of each bench will be put in outDir.");
+DEFINE_string(timers, "cg", "Timers to display. "
+              "Options: w(all) W(all, truncated) c(pu) C(pu, truncated) g(pu)");
 
-static void help() {
-    SkString configsStr;
-    static const size_t kConfigCount = SK_ARRAY_COUNT(gConfigs);
-    for (size_t i = 0; i < kConfigCount; ++i) {
-        configsStr.appendf("%s%s", gConfigs[i].fName, ((i == kConfigCount - 1) ? "" : "|"));
-    }
+DEFINE_bool(rotate, false,  "Rotate canvas before bench run?");
+DEFINE_bool(scale,  false,  "Scale canvas before bench run?");
+DEFINE_bool(clip,   false,  "Clip canvas before bench run?");
 
-    SkDebugf("Usage: bench [-o outDir] [--repeat nr] [--logPerIter] "
-                          "[--timers [wcgWC]*] [--rotate]\n"
-             "    [--scale] [--clip] [--min] [--forceAA 1|0] [--forceFilter 1|0]\n"
-             "    [--forceDither 1|0] [--forceBlend 1|0]"
-#if SK_SUPPORT_GPU
-             " [--gpuCacheSize <bytes> <count>]"
-#endif
-             "\n"
-             "    [--strokeWidth width] [--match name]\n"
-             "    [--mode normal|deferred|deferredSilent|record|picturerecord]\n"
-             "    [--config ");
-    SkDebugf("%s]\n", configsStr.c_str());
-    SkDebugf("    [-Dfoo bar] [--logFile filename] [-h|--help]");
-    SkDebugf("\n\n");
-    SkDebugf("    -o outDir : Image of each bench will be put in outDir.\n");
-    SkDebugf("    --repeat nr : Each bench repeats for nr times.\n");
-    SkDebugf("    --logPerIter : "
-             "Log each repeat timer instead of mean, default is disabled.\n");
-    SkDebugf("    --timers [wcgWC]* : "
-             "Display wall, cpu, gpu, truncated wall or truncated cpu time for each bench.\n");
-    SkDebugf("    --rotate : Rotate before each bench runs.\n");
-    SkDebugf("    --scale : Scale before each bench runs.\n");
-    SkDebugf("    --clip : Clip before each bench runs.\n");
-    SkDebugf("    --min : Print the minimum times (instead of average).\n");
-    SkDebugf("    --forceAA 1|0 : "
-             "Enable/disable anti-aliased, default is enabled.\n");
-    SkDebugf("    --forceFilter 1|0 : "
-             "Enable/disable bitmap filtering, default is disabled.\n");
-    SkDebugf("    --forceDither 1|0 : "
-             "Enable/disable dithering, default is disabled.\n");
-    SkDebugf("    --forceBlend 1|0 : "
-             "Enable/disable dithering, default is disabled.\n");
-#if SK_SUPPORT_GPU
-    SkDebugf("    --gpuCacheSize <bytes> <count>: "
-             "limits gpu cache to  bytes size or object count.\n");
-    SkDebugf("      -1 for either value means use the default. 0 for either disables the cache.\n");
-#endif
-    SkDebugf("    --strokeWidth width : The width for path stroke.\n");
-    SkDebugf("    --match [~][^]substring[$] [...] of test name to run.\n"
-             "             Multiple matches may be separated by spaces.\n"
-             "             ~ causes a matching test to always be skipped\n"
-             "             ^ requires the start of the test to match\n"
-             "             $ requires the end of the test to match\n"
-             "             ^ and $ requires an exact match\n"
-             "             If a test does not match any list entry,\n"
-             "             it is skipped unless some list entry starts with ~\n");
-    SkDebugf("    --mode normal|deferred|deferredSilent|record|picturerecord :\n"
-             "             Run in the corresponding mode\n"
-             "                 normal, Use a normal canvas to draw to;\n"
-             "                 deferred, Use a deferrred canvas when drawing;\n"
-             "                 deferredSilent, deferred with silent playback;\n"
-             "                 record, Benchmark the time to record to an SkPicture;\n"
-             "                 picturerecord, Benchmark the time to do record from a \n"
-             "                                SkPicture to a SkPicture.\n");
-    SkDebugf("    --logFile filename : destination for writing log output, in addition to stdout.\n");
-    SkDebugf("    --config %s:\n", configsStr.c_str());
-    SkDebugf("             Run bench in corresponding config mode.\n");
-    SkDebugf("    -Dfoo bar : Add extra definition to bench.\n");
-    SkDebugf("    -h|--help : Show this help message.\n");
-}
+DEFINE_bool(forceAA,        true,     "Force anti-aliasing?");
+DEFINE_bool(forceFilter,    false,    "Force bitmap filtering?");
+DEFINE_string(forceDither, "default", "Force dithering: true, false, or default?");
+DEFINE_bool(forceBlend,     false,    "Force alpha blending?");
+
+DEFINE_int32(gpuCacheBytes, -1, "GPU cache size limit in bytes.  0 to disable cache.");
+DEFINE_int32(gpuCacheCount, -1, "GPU cache size limit in object count.  0 to disable cache.");
+
+DEFINE_string(match, "",  "[~][^]substring[$] [...] of test name to run.\n"
+                          "Multiple matches may be separated by spaces.\n"
+                          "~ causes a matching test to always be skipped\n"
+                          "^ requires the start of the test to match\n"
+                          "$ requires the end of the test to match\n"
+                          "^ and $ requires an exact match\n"
+                          "If a test does not match any list entry,\n"
+                          "it is skipped unless some list entry starts with ~\n");
+DEFINE_string(mode, "normal",
+             "normal:         draw to a normal canvas;\n"
+             "deferred:       draw to a deferred canvas;\n"
+             "deferredSilent: deferred with silent playback;\n"
+             "record:         draw to an SkPicture;\n"
+             "picturerecord:  draw from an SkPicture to an SkPicture.\n");
+DEFINE_string(config, "", "Run configs given.  If empty, runs the defaults set in gConfigs.");
+DEFINE_string(logFile, "", "Also write stdout here.");
+DEFINE_int32(benchMs, 20, "Target time in ms to run each benchmark config.");
+DEFINE_string(timeFormat, "%9.2f", "Format to print results, in milliseconds per 1000 loops.");
 
 int tool_main(int argc, char** argv);
 int tool_main(int argc, char** argv) {
@@ -349,289 +279,79 @@
     gPrintInstCount = true;
 #endif
     SkAutoGraphics ag;
+    SkCommandLineFlags::Parse(argc, argv);
 
-    SkTDict<const char*> defineDict(1024);
-    int repeatDraw = 1;
-
-    int forceAlpha = 0xFF;
-    bool forceAA = true;
-    bool forceFilter = false;
-    SkTriState::State forceDither = SkTriState::kDefault;
-
-    static const uint32_t kDefaultTimerTypes = TimerData::kCpu_Flag | TimerData::kGpu_Flag;
-    static const TimerData::Result kDefaultTimerResult = TimerData::kAvg_Result;
-    uint32_t timerTypes = kDefaultTimerTypes;
-    TimerData::Result timerResult = kDefaultTimerResult;
-
-    bool doScale = false;
-    bool doRotate = false;
-    bool doClip = false;
-    bool hasStrokeWidth = false;
-
-#if SK_SUPPORT_GPU
-    struct {
-        int     fBytes;
-        int     fCount;
-    } gpuCacheSize = { -1, -1 }; // -1s mean use the default
-#endif
-
-    float strokeWidth;
-    SkTDArray<const char*> fMatches;
-    benchModes benchMode = kNormal_benchModes;
-    SkString perIterTimeformat("%.2f");
-    SkString normalTimeFormat("%6.2f");
-
-    SkString outDir;
-    SkBitmap::Config outConfig = SkBitmap::kNo_Config;
-    const char* configName = "";
-    Backend backend = kRaster_Backend;  // for warning
-    int sampleCount = 0;
-    SkTDArray<int> configs;
-    bool userConfig = false;
+    // First, parse some flags.
 
     SkBenchLogger logger;
+    if (FLAGS_logFile.count()) {
+        logger.SetLogFile(FLAGS_logFile[0]);
+    }
 
-    char* const* stop = argv + argc;
-    for (++argv; argv < stop; ++argv) {
-        if (strcmp(*argv, "-o") == 0) {
-            argv++;
-            if (argv < stop && **argv) {
-                outDir.set(*argv);
-                if (outDir.c_str()[outDir.size() - 1] != '/') {
-                    outDir.append("/");
-                }
-            }
-        } else if (strcmp(*argv, "--repeat") == 0) {
-            argv++;
-            if (argv < stop) {
-                repeatDraw = atoi(*argv);
-                if (repeatDraw < 1) {
-                    repeatDraw = 1;
-                }
-            } else {
-                logger.logError("missing arg for --repeat\n");
-                help();
-                return -1;
-            }
-        } else if (strcmp(*argv, "--logPerIter") == 0) {
-            timerResult = TimerData::kPerIter_Result;
-        } else if (strcmp(*argv, "--timers") == 0) {
-            argv++;
-            if (argv < stop) {
-                timerTypes = 0;
-                for (char* t = *argv; *t; ++t) {
-                    switch (*t) {
-                    case 'w': timerTypes |= TimerData::kWall_Flag; break;
-                    case 'c': timerTypes |= TimerData::kCpu_Flag; break;
-                    case 'W': timerTypes |= TimerData::kTruncatedWall_Flag; break;
-                    case 'C': timerTypes |= TimerData::kTruncatedCpu_Flag; break;
-                    case 'g': timerTypes |= TimerData::kGpu_Flag; break;
-                    }
-                }
-            } else {
-                logger.logError("missing arg for --timers\n");
-                help();
-                return -1;
-            }
-        } else if (!strcmp(*argv, "--rotate")) {
-            doRotate = true;
-        } else if (!strcmp(*argv, "--scale")) {
-            doScale = true;
-        } else if (!strcmp(*argv, "--clip")) {
-            doClip = true;
-        } else if (!strcmp(*argv, "--min")) {
-            timerResult = TimerData::kMin_Result;
-        } else if (strcmp(*argv, "--forceAA") == 0) {
-            if (!parse_bool_arg(++argv, stop, &forceAA)) {
-                logger.logError("missing arg for --forceAA\n");
-                help();
-                return -1;
-            }
-        } else if (strcmp(*argv, "--forceFilter") == 0) {
-            if (!parse_bool_arg(++argv, stop, &forceFilter)) {
-                logger.logError("missing arg for --forceFilter\n");
-                help();
-                return -1;
-            }
-        } else if (strcmp(*argv, "--forceDither") == 0) {
-            bool tmp;
-            if (!parse_bool_arg(++argv, stop, &tmp)) {
-                logger.logError("missing arg for --forceDither\n");
-                help();
-                return -1;
-            }
-            forceDither = tmp ? SkTriState::kTrue : SkTriState::kFalse;
-        } else if (strcmp(*argv, "--forceBlend") == 0) {
-            bool wantAlpha = false;
-            if (!parse_bool_arg(++argv, stop, &wantAlpha)) {
-                logger.logError("missing arg for --forceBlend\n");
-                help();
-                return -1;
-            }
-            forceAlpha = wantAlpha ? 0x80 : 0xFF;
-#if SK_SUPPORT_GPU
-        } else if (strcmp(*argv, "--gpuCacheSize") == 0) {
-            if (stop - argv > 2) {
-                gpuCacheSize.fBytes = atoi(*++argv);
-                gpuCacheSize.fCount = atoi(*++argv);
-            } else {
-                SkDebugf("missing arg for --gpuCacheSize\n");
-                help();
-                return -1;
-            }
-#endif
-        } else if (strcmp(*argv, "--mode") == 0) {
-            argv++;
-            if (argv < stop) {
-                if (strcmp(*argv, "normal") == 0) {
-                    benchMode = kNormal_benchModes;
-                } else if (strcmp(*argv, "deferred") == 0) {
-                    benchMode = kDeferred_benchModes;
-                } else if (strcmp(*argv, "deferredSilent") == 0) {
-                    benchMode = kDeferredSilent_benchModes;
-                } else if (strcmp(*argv, "record") == 0) {
-                    benchMode = kRecord_benchModes;
-                } else if (strcmp(*argv, "picturerecord") == 0) {
-                    benchMode = kPictureRecord_benchModes;
-                } else {
-                    logger.logError("bad arg for --mode\n");
-                    help();
-                    return -1;
-                }
-            } else {
-                logger.logError("missing arg for --mode\n");
-                help();
-                return -1;
-            }
-        } else if (strcmp(*argv, "--strokeWidth") == 0) {
-            argv++;
-            if (argv < stop) {
-                const char *strokeWidthStr = *argv;
-                if (sscanf(strokeWidthStr, "%f", &strokeWidth) != 1) {
-                  logger.logError("bad arg for --strokeWidth\n");
-                  help();
-                  return -1;
-                }
-                hasStrokeWidth = true;
-            } else {
-                logger.logError("missing arg for --strokeWidth\n");
-                help();
-                return -1;
-            }
-        } else if (strcmp(*argv, "--match") == 0) {
-            argv++;
-            while (argv < stop && (*argv)[0] != '-') {
-                *fMatches.append() = *argv++;
-            }
-            argv--;
-            if (!fMatches.count()) {
-                logger.logError("missing arg for --match\n");
-                help();
-                return -1;
-            }
-        } else if (strcmp(*argv, "--config") == 0) {
-            argv++;
-            if (argv < stop) {
-                int index = findConfig(*argv);
-                if (index >= 0) {
-                    *configs.append() = index;
-                    userConfig = true;
-                } else {
-                    SkString str;
-                    str.printf("unrecognized config %s\n", *argv);
-                    logger.logError(str);
-                    help();
-                    return -1;
-                }
-            } else {
-                logger.logError("missing arg for --config\n");
-                help();
-                return -1;
-            }
-        } else if (strcmp(*argv, "--logFile") == 0) {
-            argv++;
-            if (argv < stop) {
-                if (!logger.SetLogFile(*argv)) {
-                    SkString str;
-                    str.printf("Could not open %s for writing.", *argv);
-                    logger.logError(str);
-                    return -1;
-                }
-            } else {
-                logger.logError("missing arg for --logFile\n");
-                help();
-                return -1;
-            }
-        } else if (strlen(*argv) > 2 && strncmp(*argv, "-D", 2) == 0) {
-            argv++;
-            if (argv < stop) {
-                defineDict.set(argv[-1] + 2, *argv);
-            } else {
-                logger.logError("incomplete '-Dfoo bar' definition\n");
-                help();
-                return -1;
-            }
-        } else if (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0) {
-            help();
-            return 0;
-        } else {
-            SkString str;
-            str.printf("unrecognized arg %s\n", *argv);
-            logger.logError(str);
-            help();
-            return -1;
+    const uint8_t alpha = FLAGS_forceBlend ? 0x80 : 0xFF;
+    SkTriState::State dither = SkTriState::kDefault;
+    for (size_t i = 0; i < 3; i++) {
+        if (strcmp(SkTriState::Name[i], FLAGS_forceDither[0]) == 0) {
+            dither = static_cast<SkTriState::State>(i);
         }
     }
-    if ((benchMode == kRecord_benchModes || benchMode == kPictureRecord_benchModes)
-            && !outDir.isEmpty()) {
-        logger.logError("'--mode record' and '--mode picturerecord' are not"
-                  " compatible with -o.\n");
-        return -1;
+
+    BenchMode benchMode = kNormal_BenchMode;
+    for (size_t i = 0; i < SK_ARRAY_COUNT(BenchMode_Name); i++) {
+        if (strcmp(FLAGS_mode[0], BenchMode_Name[i]) == 0) {
+            benchMode = static_cast<BenchMode>(i);
+        }
     }
-    if ((benchMode == kRecord_benchModes || benchMode == kPictureRecord_benchModes)) {
-        perIterTimeformat.set("%.4f");
-        normalTimeFormat.set("%6.4f");
+
+    SkTDArray<int> configs;
+    // Try user-given configs first.
+    for (int i = 0; i < FLAGS_config.count(); i++) {
+        for (size_t j = 0; j < SK_ARRAY_COUNT(gConfigs); j++) {
+            if (0 == strcmp(FLAGS_config[i], gConfigs[j].name)) {
+                *configs.append() = j;
+            }
+        }
     }
-    if (!userConfig) {
-        // if no config is specified by user, add the default configs
-        for (unsigned int i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
-            if (gConfigs[i].fRunByDefault) {
+    // If there weren't any, fill in with defaults.
+    if (configs.count() == 0) {
+        for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
+            if (gConfigs[i].runByDefault) {
                 *configs.append() = i;
             }
         }
     }
-    if (kNormal_benchModes != benchMode) {
+    // Filter out things we can't run.
+    if (kNormal_BenchMode != benchMode) {
         // Non-rendering configs only run in normal mode
         for (int i = 0; i < configs.count(); ++i) {
-            int configIdx = configs[i];
-            if (kNonRendering_Backend == gConfigs[configIdx].fBackend) {
+            const Config& config = gConfigs[configs[i]];
+            if (kNonRendering_Backend == config.backend) {
                 configs.remove(i, 1);
                 --i;
             }
         }
     }
-
 #if SK_SUPPORT_GPU
     for (int i = 0; i < configs.count(); ++i) {
-        int configIdx = configs[i];
+        const Config& config = gConfigs[configs[i]];
 
-        if (kGPU_Backend == gConfigs[configIdx].fBackend && gConfigs[configIdx].fSampleCnt > 0) {
-            GrContext* context = gContextFactory.get(gConfigs[configIdx].fContextType);
+        if (kGPU_Backend == config.backend) {
+            GrContext* context = gContextFactory.get(config.contextType);
             if (NULL == context) {
                 SkString error;
                 error.printf("Error creating GrContext for config %s. Config will be skipped.\n",
-                             gConfigs[configIdx].fName);
-                logger.logError(error.c_str());
+                             config.name);
+                logger.logError(error);
                 configs.remove(i);
                 --i;
                 continue;
             }
-            if (gConfigs[configIdx].fSampleCnt > context->getMaxSampleCount()){
+            if (config.sampleCount > context->getMaxSampleCount()){
                 SkString error;
                 error.printf("Sample count (%d) for config %s is unsupported. "
                              "Config will be skipped.\n",
-                             gConfigs[configIdx].fSampleCnt, gConfigs[configIdx].fName);
-                logger.logError(error.c_str());
+                             config.sampleCount, config.name);
+                logger.logError(error);
                 configs.remove(i);
                 --i;
                 continue;
@@ -640,334 +360,272 @@
     }
 #endif
 
-    // report our current settings
-    {
-        SkString str;
-        const char* deferredMode = benchMode == kDeferred_benchModes ? "yes" :
-            (benchMode == kDeferredSilent_benchModes ? "silent" : "no");
-        str.printf("skia bench: alpha=0x%02X antialias=%d filter=%d "
-                   "deferred=%s logperiter=%d",
-                   forceAlpha, forceAA, forceFilter, deferredMode,
-                   TimerData::kPerIter_Result == timerResult);
-        str.appendf(" rotate=%d scale=%d clip=%d min=%d",
-                   doRotate, doScale, doClip, TimerData::kMin_Result == timerResult);
-        str.appendf(" record=%d picturerecord=%d",
-                    benchMode == kRecord_benchModes,
-                    benchMode == kPictureRecord_benchModes);
-        const char * ditherName;
-        switch (forceDither) {
-            case SkTriState::kDefault: ditherName = "default"; break;
-            case SkTriState::kTrue: ditherName = "true"; break;
-            case SkTriState::kFalse: ditherName = "false"; break;
-            default: ditherName = "<invalid>"; break;
-        }
-        str.appendf(" dither=%s", ditherName);
+    // All flags should be parsed now.  Report our settings.
+    if (kIsDebug) {
+        logger.logError("bench was built in Debug mode, so we're going to hide the times."
+                        "  It's for your own good!\n");
+    }
+    SkString str("skia bench:");
+    str.appendf(" mode=%s", FLAGS_mode[0]);
+    str.appendf(" alpha=0x%02X antialias=%d filter=%d dither=%s",
+                alpha, FLAGS_forceAA, FLAGS_forceFilter, SkTriState::Name[dither]);
+    str.appendf(" rotate=%d scale=%d clip=%d", FLAGS_rotate, FLAGS_scale, FLAGS_clip);
 
-        if (hasStrokeWidth) {
-            str.appendf(" strokeWidth=%f", strokeWidth);
-        } else {
-            str.append(" strokeWidth=none");
-        }
-
-#if defined(SK_SCALAR_IS_FLOAT)
-        str.append(" scalar=float");
-#elif defined(SK_SCALAR_IS_FIXED)
-        str.append(" scalar=fixed");
+#if defined(SK_SCALAR_IS_FIXED)
+    str.append(" scalar=fixed");
+#else
+    str.append(" scalar=float");
 #endif
 
 #if defined(SK_BUILD_FOR_WIN32)
-        str.append(" system=WIN32");
+    str.append(" system=WIN32");
 #elif defined(SK_BUILD_FOR_MAC)
-        str.append(" system=MAC");
+    str.append(" system=MAC");
 #elif defined(SK_BUILD_FOR_ANDROID)
-        str.append(" system=ANDROID");
+    str.append(" system=ANDROID");
 #elif defined(SK_BUILD_FOR_UNIX)
-        str.append(" system=UNIX");
+    str.append(" system=UNIX");
 #else
-        str.append(" system=other");
+    str.append(" system=other");
 #endif
 
 #if defined(SK_DEBUG)
-        str.append(" DEBUG");
+    str.append(" DEBUG");
 #endif
-        str.append("\n");
-        logger.logProgress(str);
-    }
+    str.append("\n");
+    logger.logProgress(str);
 
-    SkTArray<BenchTimer*> timers(SK_ARRAY_COUNT(gConfigs));
+
+    // Set texture cache limits if non-default.
     for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
 #if SK_SUPPORT_GPU
-        SkGLContextHelper* glCtx = NULL;
-        if (kGPU_Backend == gConfigs[i].fBackend) {
-            GrContext* context = gContextFactory.get(gConfigs[i].fContextType);
-            if (NULL != context) {
-                // Set the user specified cache limits if non-default.
-                size_t bytes;
-                int count;
-                context->getTextureCacheLimits(&count, &bytes);
-                if (-1 != gpuCacheSize.fBytes) {
-                    bytes = static_cast<size_t>(gpuCacheSize.fBytes);
-                }
-                if (-1 != gpuCacheSize.fCount) {
-                    count = gpuCacheSize.fCount;
-                }
-                context->setTextureCacheLimits(count, bytes);
-            }
-            glCtx = gContextFactory.getGLContext(gConfigs[i].fContextType);
+        const Config& config = gConfigs[i];
+        if (kGPU_Backend != config.backend) {
+            continue;
         }
-        timers.push_back(SkNEW_ARGS(BenchTimer, (glCtx)));
-#else
-        timers.push_back(SkNEW(BenchTimer));
+        GrContext* context = gContextFactory.get(config.contextType);
+        if (NULL == context) {
+            continue;
+        }
+
+        size_t bytes;
+        int count;
+        context->getTextureCacheLimits(&count, &bytes);
+        if (-1 != FLAGS_gpuCacheBytes) {
+            bytes = static_cast<size_t>(FLAGS_gpuCacheBytes);
+        }
+        if (-1 != FLAGS_gpuCacheCount) {
+            count = FLAGS_gpuCacheCount;
+        }
+        context->setTextureCacheLimits(count, bytes);
 #endif
     }
 
-    Iter iter(&defineDict);
+    // Find the longest name of the benches we're going to run to make the output pretty.
+    Iter names;
     SkBenchmark* bench;
+    int longestName = 0;
+    while ((bench = names.next()) != NULL) {
+        SkAutoTUnref<SkBenchmark> benchUnref(bench);
+        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
+            continue;
+        }
+        const int length = strlen(bench->getName());
+        longestName = length > longestName ? length : longestName;
+    }
+
+    // Run each bench in each configuration it supports and we asked for.
+    Iter iter;
     while ((bench = iter.next()) != NULL) {
         SkAutoTUnref<SkBenchmark> benchUnref(bench);
-
-        SkIPoint dim = bench->getSize();
-        if (dim.fX <= 0 || dim.fY <= 0) {
+        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getName())) {
             continue;
         }
 
-        bench->setForceAlpha(forceAlpha);
-        bench->setForceAA(forceAA);
-        bench->setForceFilter(forceFilter);
-        bench->setDither(forceDither);
-        if (hasStrokeWidth) {
-            bench->setStrokeWidth(strokeWidth);
-        }
-
-        // only run benchmarks if their name contains matchStr
-        if (SkCommandLineFlags::ShouldSkip(fMatches, bench->getName())) {
-            continue;
-        }
-
-        bool loggedBenchStart = false;
-
+        bench->setForceAlpha(alpha);
+        bench->setForceAA(FLAGS_forceAA);
+        bench->setForceFilter(FLAGS_forceFilter);
+        bench->setDither(dither);
         AutoPrePostDraw appd(bench);
 
-        for (int x = 0; x < configs.count(); ++x) {
-            int configIndex = configs[x];
+        bool loggedBenchName = false;
+        for (int i = 0; i < configs.count(); ++i) {
+            const int configIndex = configs[i];
+            const Config& config = gConfigs[configIndex];
 
-            bool setupFailed = false;
-
-            if (kNonRendering_Backend == gConfigs[configIndex].fBackend) {
-                if (bench->isRendering()) {
-                    continue;
-                }
-            } else {
-                if (!bench->isRendering()) {
-                    continue;
-                }
+            if ((kNonRendering_Backend == config.backend) == bench->isRendering()) {
+                continue;
             }
 
-            outConfig = gConfigs[configIndex].fConfig;
-            configName = gConfigs[configIndex].fName;
-            backend = gConfigs[configIndex].fBackend;
-            sampleCount = gConfigs[configIndex].fSampleCnt;
             GrContext* context = NULL;
-            BenchTimer* timer = timers[configIndex];
-
 #if SK_SUPPORT_GPU
             SkGLContextHelper* glContext = NULL;
-            if (kGPU_Backend == backend) {
-                context = gContextFactory.get(gConfigs[configIndex].fContextType);
+            if (kGPU_Backend == config.backend) {
+                context = gContextFactory.get(config.contextType);
                 if (NULL == context) {
                     continue;
                 }
-                glContext = gContextFactory.getGLContext(gConfigs[configIndex].fContextType);
+                glContext = gContextFactory.getGLContext(config.contextType);
             }
 #endif
-            SkBaseDevice* device = NULL;
-            SkCanvas* canvas = NULL;
-            SkPicture pictureRecordFrom;
-            SkPicture pictureRecordTo;
+            SkAutoTUnref<SkBaseDevice> device;
+            SkAutoTUnref<SkCanvas> canvas;
+            SkPicture recordFrom, recordTo;
+            const SkIPoint dim = bench->getSize();
 
-            if (kNonRendering_Backend != backend) {
-                device = make_device(outConfig, dim, backend, sampleCount, context);
-                if (NULL == device) {
+            const SkPicture::RecordingFlags kRecordFlags =
+                SkPicture::kUsePathBoundsForClip_RecordingFlag;
+
+            if (kNonRendering_Backend != config.backend) {
+                device.reset(make_device(config.config,
+                                         dim,
+                                         config.backend,
+                                         config.sampleCount,
+                                         context));
+                if (!device.get()) {
                     SkString error;
-                    error.printf("Device creation failure for config %s. Will skip.\n", configName);
-                    logger.logError(error.c_str());
-                    setupFailed = true;
-                } else {
-                    switch(benchMode) {
-                        case kDeferredSilent_benchModes:
-                        case kDeferred_benchModes:
-                            canvas = SkDeferredCanvas::Create(device);
-                            break;
-                        case kRecord_benchModes:
-                            canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
-                                SkPicture::kUsePathBoundsForClip_RecordingFlag);
-                            canvas->ref();
-                            break;
-                        case kPictureRecord_benchModes: {
-                            // This sets up picture-to-picture recording.
-                            // The C++ drawing calls for the benchmark are recorded into
-                            // pictureRecordFrom. As the benchmark, we will time how
-                            // long it takes to playback pictureRecordFrom into
-                            // pictureRecordTo.
-                            SkCanvas* tempCanvas = pictureRecordFrom.beginRecording(dim.fX, dim.fY,
-                                SkPicture::kUsePathBoundsForClip_RecordingFlag);
-                            bench->draw(tempCanvas);
-                            pictureRecordFrom.endRecording();
-                            canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
-                                SkPicture::kUsePathBoundsForClip_RecordingFlag);
-                            canvas->ref();
-                            break;
-                        }
-                        case kNormal_benchModes:
-                            canvas = new SkCanvas(device);
-                            break;
-                        default:
-                            SkASSERT(0);
-                    }
-                    device->unref();
-                    canvas->clear(SK_ColorWHITE);
-                }
-            }
-            SkAutoUnref canvasUnref(canvas);
-            if (!setupFailed) {
-                if (NULL != canvas) {
-                    if (doClip) {
-                        performClip(canvas, dim.fX, dim.fY);
-                    }
-                    if (doScale) {
-                        performScale(canvas, dim.fX, dim.fY);
-                    }
-                    if (doRotate) {
-                        performRotate(canvas, dim.fX, dim.fY);
-                    }
+                    error.printf("Device creation failure for config %s. Will skip.\n", config.name);
+                    logger.logError(error);
+                    continue;
                 }
 
-                if (!loggedBenchStart) {
-                    loggedBenchStart = true;
+                switch(benchMode) {
+                    case kDeferredSilent_BenchMode:
+                    case kDeferred_BenchMode:
+                        canvas.reset(SkDeferredCanvas::Create(device.get()));
+                        break;
+                    case kRecord_BenchMode:
+                        canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
+                        break;
+                    case kPictureRecord_BenchMode:
+                        bench->draw(recordFrom.beginRecording(dim.fX, dim.fY, kRecordFlags));
+                        recordFrom.endRecording();
+                        canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
+                        break;
+                    case kNormal_BenchMode:
+                        canvas.reset(new SkCanvas(device.get()));
+                        break;
+                    default:
+                        SkASSERT(false);
+                }
+            }
+
+            if (NULL != canvas) {
+                canvas->clear(SK_ColorWHITE);
+                if (FLAGS_clip)   {   performClip(canvas, dim.fX, dim.fY); }
+                if (FLAGS_scale)  {  performScale(canvas, dim.fX, dim.fY); }
+                if (FLAGS_rotate) { performRotate(canvas, dim.fX, dim.fY); }
+            }
+
+            if (!loggedBenchName) {
+                loggedBenchName = true;
+                SkString str;
+                str.printf("running bench [%3d %3d] %*s ",
+                           dim.fX, dim.fY, longestName, bench->getName());
+                logger.logProgress(str);
+            }
+
+#if SK_SUPPORT_GPU
+            SkGLContextHelper* contextHelper = NULL;
+            if (kGPU_Backend == config.backend) {
+                contextHelper = gContextFactory.getGLContext(config.contextType);
+            }
+            BenchTimer timer(contextHelper);
+#else
+            BenchTimer timer;
+#endif
+
+            bench->setLoops(0);
+            do {
+                // Ramp up 1 -> 4 -> 16 -> ... -> ~1 billion.
+                const int loops = bench->getLoops();
+                if (loops >= (1<<30)) {
+                    // If you find it takes more than a billion loops to get up to 20ms of runtime,
+                    // you've got a computer clocked at several THz or have a broken benchmark.  ;)
+                    //     "1B ought to be enough for anybody."
                     SkString str;
-                    str.printf("running bench [%d %d] %28s", dim.fX, dim.fY, bench->getName());
-                    logger.logProgress(str);
+                    str.printf("Can't ramp %s to %dms.\n", bench->getName(), FLAGS_benchMs);
+                    logger.logError(str);
+                    break;
+                }
+                bench->setLoops(loops == 0 ? 1 : loops * 4);
+
+                if ((benchMode == kRecord_BenchMode || benchMode == kPictureRecord_BenchMode)) {
+                    // Clear the recorded commands so that they do not accumulate.
+                    canvas.reset(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags));
                 }
 
-                // warm up caches if needed
-                if (repeatDraw > 1 && NULL != canvas) {
-#if SK_SUPPORT_GPU
-                    // purge the GPU resources to reduce variance
-                    if (NULL != context) {
-                        context->freeGpuResources();
-                    }
-#endif
-                    SkAutoCanvasRestore acr(canvas, true);
-                    if (benchMode == kPictureRecord_benchModes) {
-                        pictureRecordFrom.draw(canvas);
-                    } else {
-                        bench->draw(canvas);
-                    }
-
-                    if (kDeferredSilent_benchModes == benchMode) {
-                        static_cast<SkDeferredCanvas*>(canvas)->silentFlush();
-                    } else {
-                        canvas->flush();
-                    }
-#if SK_SUPPORT_GPU
-                    if (NULL != context) {
-                        context->flush();
-                        SK_GL(*glContext, Finish());
-                    }
-#endif
+                timer.start();
+                if (NULL != canvas) {
+                    canvas->save();
                 }
-
-                // record timer values for each repeat, and their sum
-                TimerData timerData(repeatDraw);
-                for (int i = 0; i < repeatDraw; i++) {
-                    if ((benchMode == kRecord_benchModes || benchMode == kPictureRecord_benchModes)) {
-                        // This will clear the recorded commands so that they do not
-                        // accumulate.
-                        canvas = pictureRecordTo.beginRecording(dim.fX, dim.fY,
-                            SkPicture::kUsePathBoundsForClip_RecordingFlag);
-                    }
-
-                    timer->start(bench->getDurationScale());
-                    if (NULL != canvas) {
-                        canvas->save();
-                    }
-                    if (benchMode == kPictureRecord_benchModes) {
-                        pictureRecordFrom.draw(canvas);
-                    } else {
-                        bench->draw(canvas);
-                    }
-
-                    if (kDeferredSilent_benchModes == benchMode) {
-                        static_cast<SkDeferredCanvas*>(canvas)->silentFlush();
-                    } else if (NULL != canvas) {
-                        canvas->flush();
-                    }
-
-                    if (NULL != canvas) {
-                        canvas->restore();
-                    }
-
-                    // stop the truncated timer after the last canvas call but
-                    // don't wait for all the GL calls to complete
-                    timer->truncatedEnd();
-#if SK_SUPPORT_GPU
-                    if (NULL != glContext) {
-                        context->flush();
-                        SK_GL(*glContext, Finish());
-                    }
-#endif
-                    // stop the inclusive and gpu timers once all the GL calls
-                    // have completed
-                    timer->end();
-
-                    SkAssertResult(timerData.appendTimes(timer));
-
-                }
-                const char* timeFormat;
-                if (repeatDraw > 1 && TimerData::kPerIter_Result == timerResult) {
-                    timeFormat = perIterTimeformat.c_str();
+                if (benchMode == kPictureRecord_BenchMode) {
+                    recordFrom.draw(canvas);
                 } else {
-                    timeFormat = normalTimeFormat.c_str();
+                    bench->draw(canvas);
                 }
-                uint32_t filteredTimerTypes = timerTypes;
-                if (NULL == context) {
-                    filteredTimerTypes &= ~TimerData::kGpu_Flag;
-                }
-                SkString result = timerData.getResult(timeFormat,
-                                    timerResult,
-                                    configName,
-                                    filteredTimerTypes);
-                logger.logProgress(result);
 
-                if (outDir.size() > 0 && kNonRendering_Backend != backend) {
-                    saveFile(bench->getName(), configName, outDir.c_str(),
-                             device->accessBitmap(false));
+                if (kDeferredSilent_BenchMode == benchMode) {
+                    static_cast<SkDeferredCanvas*>(canvas.get())->silentFlush();
+                } else if (NULL != canvas) {
+                    canvas->flush();
+                }
+
+                if (NULL != canvas) {
+                    canvas->restore();
+                }
+
+
+                // Stop truncated timers before GL calls complete, and stop the full timers after.
+                timer.truncatedEnd();
+#if SK_SUPPORT_GPU
+                if (NULL != glContext) {
+                    context->flush();
+                    SK_GL(*glContext, Finish());
+                }
+#endif
+                timer.end();
+            } while (!kIsDebug && timer.fWall < FLAGS_benchMs);  // One loop only in debug mode.
+
+            if (FLAGS_outDir.count() && kNonRendering_Backend != config.backend) {
+                saveFile(bench->getName(),
+                         config.name,
+                         FLAGS_outDir[0],
+                         device->accessBitmap(false));
+            }
+
+            if (kIsDebug) {
+                // Let's not mislead ourselves by looking at Debug build bench times!
+                continue;
+            }
+
+            // Normalize to ms per 1000 iterations.
+            const double normalize = 1000.0 / bench->getLoops();
+            const struct { char shortName; const char* longName; double ms; } times[] = {
+                {'w', "msecs",  normalize * timer.fWall},
+                {'W', "Wmsecs", normalize * timer.fTruncatedWall},
+                {'c', "cmsecs", normalize * timer.fCpu},
+                {'C', "Cmsecs", normalize * timer.fTruncatedCpu},
+                {'g', "gmsecs", normalize * timer.fGpu},
+            };
+
+            SkString result;
+            result.appendf("   %s:", config.name);
+            for (size_t i = 0; i < SK_ARRAY_COUNT(times); i++) {
+                if (strchr(FLAGS_timers[0], times[i].shortName) && times[i].ms > 0) {
+                    result.appendf(" %s = ", times[i].longName);
+                    result.appendf(FLAGS_timeFormat[0], times[i].ms);
                 }
             }
+            logger.logProgress(result);
         }
-        if (loggedBenchStart) {
-            logger.logProgress(SkString("\n"));
+        if (loggedBenchName) {
+            logger.logProgress("\n");
         }
     }
 #if SK_SUPPORT_GPU
-#if GR_CACHE_STATS
-    for (int i = 0; i <= GrContextFactory::kLastGLContextType; ++i) {
-        GrContextFactory::GLContextType ctxType = (GrContextFactory::GLContextType)i;
-        GrContext* context = gContextFactory.get(ctxType);
-        if (NULL != context) {
-            SkDebugf("Cache Stats for %s context:\n", GrContextFactory::GLContextTypeName(ctxType));
-            context->printCacheStats();
-            SkDebugf("\n");
-        }
-    }
-#endif
-    // Destroy the GrContext before the inst tracking printing at main() exit occurs.
     gContextFactory.destroyContexts();
 #endif
-    for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); ++i) {
-        SkDELETE(timers[i]);
-    }
-
     return 0;
 }
 
diff --git a/gyp/bench.gypi b/gyp/bench.gypi
index bb2f942..9f4bdb6 100644
--- a/gyp/bench.gypi
+++ b/gyp/bench.gypi
@@ -74,8 +74,6 @@
 
     '../bench/SkBenchLogger.h',
     '../bench/SkBenchLogger.cpp',
-    '../bench/TimerData.h',
-    '../bench/TimerData.cpp',
   ],
 }
 
diff --git a/tools/bbh_shootout.cpp b/tools/bbh_shootout.cpp
index 8822389..8f445d8 100644
--- a/tools/bbh_shootout.cpp
+++ b/tools/bbh_shootout.cpp
@@ -17,9 +17,9 @@
 #include "SkTArray.h"
 #include "TimerData.h"
 
-static const int kNumNormalRecordings = SkBENCHLOOP(10);
-static const int kNumRTreeRecordings = SkBENCHLOOP(10);
-static const int kNumPlaybacks = SkBENCHLOOP(1);
+static const int kNumNormalRecordings = 10;
+static const int kNumRTreeRecordings = 10;
+static const int kNumPlaybacks = 1;
 static const size_t kNumBaseBenchmarks = 3;
 static const size_t kNumTileSizes = 3;
 static const size_t kNumBbhPlaybackBenchmarks = 3;