public void doBenchmark(String[] args) {
    super.init(args);
    // IO.redirect("stdout.txt", "stderr.txt");
    final long startTime = System.currentTimeMillis();

    System.err.println(IP.localHostname() + "/ starting...");

    int concurrentSessions = Args.valueOf(args, "-threads", 1);
    String partitions = Args.valueOf(args, "-partition", "0/1");
    int site = Integer.valueOf(partitions.split("/")[0]);
    int numberOfSites = Integer.valueOf(partitions.split("/")[1]);
    // ASSUMPTION: concurrentSessions is the same at all sites
    int numberOfVirtualSites = numberOfSites * concurrentSessions;

    List<String> candidates = Args.subList(args, "-servers");
    server = ClosestDomain.closest2Domain(candidates, site);
    shepard = Args.valueOf(args, "-shepard", "");

    System.err.println(IP.localHostAddress() + " connecting to: " + server);

    super.populateWorkloadFromConfig();

    SafeLog.printlnComment("");
    SafeLog.printlnComment(String.format("\targs=%s", Arrays.asList(args)));
    SafeLog.printlnComment(String.format("\tsite=%s", site));
    SafeLog.printlnComment(String.format("\tnumberOfSites=%s", numberOfSites));
    SafeLog.printlnComment(String.format("\tthreads=%s", concurrentSessions));
    SafeLog.printlnComment(String.format("\tnumberOfVirtualSites=%s", numberOfVirtualSites));
    SafeLog.printlnComment(String.format("\tSurrogate=%s", server));
    SafeLog.printlnComment(String.format("\tShepard=%s", shepard));

    if (!shepard.isEmpty()) Shepard.sheepJoinHerd(shepard);

    // Kick off all sessions, throughput is limited by
    // concurrentSessions.
    final ExecutorService threadPool =
        Executors.newFixedThreadPool(concurrentSessions, Threading.factory("App"));

    final double sessionOpsPerMs =
        ((double) targetOpsPerSec / (double) concurrentSessions) / 1000.0;
    System.err.println("Spawning session threads.");
    for (int i = 0; i < concurrentSessions; i++) {
      final int sessionId = site * concurrentSessions + i;
      final Workload commands = getWorkloadFromConfig(sessionId, numberOfVirtualSites);
      threadPool.execute(
          new Runnable() {
            public void run() {
              // Randomize startup to avoid clients running all at the
              // same time; causes problems akin to DDOS symptoms.
              Threading.sleep(Sys.rg.nextInt(10000));
              SwiftSocialBenchmark.super.runClientSession(
                  Integer.toString(sessionId), commands, false, sessionOpsPerMs);
            }
          });
    }

    // report client progress every 10 seconds...
    final int PERIOD = 10;
    new PeriodicTask(0.0, 0.0 + PERIOD) {
      private int lastDone;

      public void run() {
        final int recentDone = commandsDone.get();
        final int throughput = (recentDone - lastDone) / PERIOD;
        lastDone = recentDone;
        System.err.printf(
            "Done: %s, throughput %d op/s\n",
            Progress.percentage(recentDone, totalCommands.get()), throughput);
      }
    };

    // Wait for all sessions.
    threadPool.shutdown();
    Threading.awaitTermination(threadPool, Integer.MAX_VALUE);

    System.err.println("Session threads completed.");
    System.err.println(
        "Throughput: "
            + totalCommands.get() * 1000 / (System.currentTimeMillis() - startTime)
            + " txns/s");
    System.exit(0);
  }