/**
   * Calls garbage collector and wait.
   *
   * @throws Exception if any thread has interrupted the current thread while waiting.
   */
  private void gc() throws Exception {
    Runtime rt = Runtime.getRuntime();

    long freeMem0 = rt.freeMemory();
    long freeMem = Long.MAX_VALUE;

    int cnt = 0;

    while (freeMem0 < freeMem && cnt < GC_CALL_CNT) {
      System.gc();

      U.sleep(WAIT_TIME);

      cnt++;

      freeMem = freeMem0;
      freeMem0 = rt.freeMemory();
    }
  }
  /** @throws Exception If failed. */
  private void doTest() throws Exception {
    System.gc();
    System.gc();
    System.gc();

    try {
      useCache = true;

      startGridsMultiThreaded(GRID_CNT);

      useCache = false;

      Ignite ignite = startGrid();

      final IgniteDataStreamer<Integer, String> ldr = ignite.dataStreamer(null);

      ldr.perNodeBufferSize(8192);
      ldr.receiver(DataStreamerCacheUpdaters.<Integer, String>batchedSorted());
      ldr.autoFlushFrequency(0);

      final LongAdder8 cnt = new LongAdder8();

      long start = U.currentTimeMillis();

      Thread t =
          new Thread(
              new Runnable() {
                @SuppressWarnings("BusyWait")
                @Override
                public void run() {
                  while (true) {
                    try {
                      Thread.sleep(10000);
                    } catch (InterruptedException ignored) {
                      break;
                    }

                    info(">>> Adds/sec: " + cnt.sumThenReset() / 10);
                  }
                }
              });

      t.setDaemon(true);

      t.start();

      int threadNum = 2; // Runtime.getRuntime().availableProcessors();

      multithreaded(
          new Callable<Object>() {
            @SuppressWarnings("InfiniteLoopStatement")
            @Override
            public Object call() throws Exception {
              ThreadLocalRandom8 rnd = ThreadLocalRandom8.current();

              while (true) {
                int i = rnd.nextInt(ENTRY_CNT);

                ldr.addData(i, vals[rnd.nextInt(vals.length)]);

                cnt.increment();
              }
            }
          },
          threadNum,
          "loader");

      info("Closing loader...");

      ldr.close(false);

      long duration = U.currentTimeMillis() - start;

      info("Finished performance test. Duration: " + duration + "ms.");
    } finally {
      stopAllGrids();
    }
  }