public void getPerformanceTest() {
    final int numEntries = 500;
    final int numCycles = 5;
    final int numGets = numCycles * numEntries;
    final int minEntrySize = 50;
    final int maxEntrySize = 1000;
    final Random random = new Random();

    File dbDir = createDbDir("getPerformanceTest");
    Environment dbEnvironment =
        BerkeleyDBViewComputationCacheSource.constructDatabaseEnvironment(dbDir, false);

    BerkeleyDBBinaryDataStore dataStore =
        new BerkeleyDBBinaryDataStore(dbEnvironment, "getPerformanceTest");
    dataStore.start();

    int randRange = maxEntrySize - minEntrySize;
    for (int i = 0; i < numEntries; i++) {
      int nBytes = minEntrySize + random.nextInt(randRange);
      byte[] bytes = new byte[nBytes];
      random.nextBytes(bytes);
      dataStore.put(i, bytes);
    }

    OperationTimer timer = new OperationTimer(s_logger, "Loading {} entries", numGets);
    for (int j = 0; j < numCycles; j++) {
      for (int i = 0; i < numEntries; i++) {
        byte[] data = dataStore.get(i);
        assertNotNull(data);
        assertTrue(data.length >= minEntrySize);
        assertTrue(data.length <= maxEntrySize);
      }
    }

    long numMillis = timer.finished();

    double msPerGet = ((double) numMillis) / ((double) numGets);
    double getsPerSecond = 1000.0 / msPerGet;

    s_logger.info(
        "for {} gets, {} ms/get, {} gets/sec", new Object[] {numGets, msPerGet, getsPerSecond});

    dataStore.delete();
    dataStore.stop();
    dbEnvironment.close();
  }
  public void putPerformanceTest() {
    final int numEntries = 5000;
    final int minEntrySize = 50;
    final int maxEntrySize = 1000;
    final Random random = new Random();

    File dbDir = createDbDir("putPerformanceTest");
    Environment dbEnvironment =
        BerkeleyDBViewComputationCacheSource.constructDatabaseEnvironment(dbDir, false);

    BerkeleyDBBinaryDataStore dataStore =
        new BerkeleyDBBinaryDataStore(dbEnvironment, "putPerformanceTest");
    dataStore.start();

    OperationTimer timer = new OperationTimer(s_logger, "Writing {} entries", numEntries);

    int randRange = maxEntrySize - minEntrySize;
    for (int i = 0; i < numEntries; i++) {
      int nBytes = minEntrySize + random.nextInt(randRange);
      byte[] bytes = new byte[nBytes];
      random.nextBytes(bytes);
      dataStore.put(i, bytes);
    }

    long numMillis = timer.finished();

    double msPerPut = ((double) numMillis) / ((double) numEntries);
    double putsPerSecond = 1000.0 / msPerPut;

    s_logger.info(
        "for {} entries, {} ms/put, {} puts/sec",
        new Object[] {numEntries, msPerPut, putsPerSecond});

    dataStore.delete();
    dataStore.stop();
    dbEnvironment.close();
  }
  public void parallelPutGetTest() throws InterruptedException {
    final int numEntries = 5000;
    final int numCycles = 1;
    final int numGets = numCycles * numEntries;
    final Random random = new Random();

    File dbDir = createDbDir("parallelPutGetTest");
    Environment dbEnvironment =
        BerkeleyDBViewComputationCacheSource.constructDatabaseEnvironment(dbDir, false);

    final BerkeleyDBBinaryDataStore dataStore =
        new BerkeleyDBBinaryDataStore(dbEnvironment, "parallelPutGetTest");
    dataStore.start();

    final AtomicLong currentMaxIdentifier = new AtomicLong(0L);
    final byte[] bytes = new byte[100];
    random.nextBytes(bytes);
    Thread tPut =
        new Thread(
            new Runnable() {
              @Override
              public void run() {
                OperationTimer timer =
                    new OperationTimer(s_logger, "Putting {} entries", numEntries);
                for (int i = 0; i < numEntries; i++) {
                  random.nextBytes(bytes);
                  dataStore.put(i, bytes);
                  currentMaxIdentifier.set(i);
                }
                long numMillis = timer.finished();

                double msPerPut = ((double) numMillis) / ((double) numGets);
                double putsPerSecond = 1000.0 / msPerPut;

                s_logger.info(
                    "for {} puts, {} ms/put, {} puts/sec",
                    new Object[] {numEntries, msPerPut, putsPerSecond});
              }
            },
            "Putter");

    class GetRunner implements Runnable {
      @Override
      public void run() {
        OperationTimer timer = new OperationTimer(s_logger, "Getting {} entries", numGets);
        for (int i = 0; i < numGets; i++) {
          int maxIdentifier = (int) currentMaxIdentifier.get();
          long actualIdentifier = random.nextInt(maxIdentifier);
          dataStore.get(actualIdentifier);
        }
        long numMillis = timer.finished();

        double msPerGet = ((double) numMillis) / ((double) numGets);
        double getsPerSecond = 1000.0 / msPerGet;

        s_logger.info(
            "for {} gets, {} ms/get, {} gets/sec", new Object[] {numGets, msPerGet, getsPerSecond});
      }
    };
    Thread tGet1 = new Thread(new GetRunner(), "getter-1");
    Thread tGet2 = new Thread(new GetRunner(), "getter-2");
    // Thread tGet3 = new Thread(new GetRunner(), "getter-3");
    // Thread tGet4 = new Thread(new GetRunner(), "getter-4");
    // Thread tGet5 = new Thread(new GetRunner(), "getter-5");

    tPut.start();
    Thread.sleep(5L);
    tGet1.start();
    tGet2.start();
    // tGet3.start();
    // tGet4.start();
    // tGet5.start();

    tPut.join();
    tGet1.join();
    tGet2.join();
    // tGet3.join();
    // tGet4.join();
    // tGet5.join();

    dataStore.delete();
    dataStore.stop();
    dbEnvironment.close();
  }