/**
   * @param g Grid.
   * @throws Exception If failed.
   */
  private void checkNodes(Ignite g) throws Exception {
    IgniteCache<String, String> cache = g.cache("test");

    for (char c = 'a'; c <= 'z'; c++) {
      String key = Character.toString(c);

      cache.put(key, "val-" + key);

      String v1 = cache.get(key);
      String v2 = cache.get(key); // Get second time.

      info("v1: " + v1);
      info("v2: " + v2);

      assertNotNull(v1);
      assertNotNull(v2);

      if (affinity(cache).mapKeyToNode(key).isLocal()) assertSame(v1, v2);
      else assertEquals(v1, v2);
    }
  }
  /** {@inheritDoc} */
  @Override
  protected void beforeTestsStarted() throws Exception {
    super.beforeTestsStarted();

    for (int i = 0; i < vals.length; i++) {
      int valLen = ThreadLocalRandom8.current().nextInt(128, 512);

      StringBuilder sb = new StringBuilder();

      for (int j = 0; j < valLen; j++) sb.append('a' + ThreadLocalRandom8.current().nextInt(20));

      vals[i] = sb.toString();

      info("Value: " + vals[i]);
    }
  }
  /** @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();
    }
  }