You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by re...@apache.org on 2020/11/04 07:19:49 UTC

[uima-uimafit] 01/01: [UIMA-6291] Improve uimaFIT benchmarking module

This is an automated email from the ASF dual-hosted git repository.

rec pushed a commit to branch feature/UIMA-6291-Improve-uimaFIT-benchmarking-module
in repository https://gitbox.apache.org/repos/asf/uima-uimafit.git

commit fc06d67e93f479d44b503223e15ab32b04d3ad3c
Author: Richard Eckart de Castilho <re...@apache.org>
AuthorDate: Wed Nov 4 08:10:03 2020 +0100

    [UIMA-6291] Improve uimaFIT benchmarking module
    
    - Added support for benchmark groups
    - Avoid re-building the CAS for every single benchmark to make benchmarks in a group more comparable
    - Provide informative summaries for groups
---
 .../java/org/apache/uima/fit/benchmark/Batch.java  |   1 +
 .../org/apache/uima/fit/benchmark/Benchmark.java   | 242 ++++++++-------
 .../uima/fit/benchmark/CasInitializationUtils.java |   6 +-
 .../uima/fit/benchmark/CasUtilBenchmark.java       |  13 +-
 .../uima/fit/benchmark/JCasUtilBenchmark.java      | 324 ++++++++++++---------
 5 files changed, 326 insertions(+), 260 deletions(-)

diff --git a/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/Batch.java b/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/Batch.java
index a4fd351..feb7a8b 100644
--- a/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/Batch.java
+++ b/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/Batch.java
@@ -63,6 +63,7 @@ public class Batch {
       sb.append(String.format("min: %4.0f ", stats.getMin()));
       sb.append(String.format("max: %4.0f ", stats.getMax()));
       sb.append(String.format("median: %4.0f ", stats.getPercentile(50)));
+      sb.append(String.format("cumulative: %6.0f ", stats.getSum()));
       sb.append(String.format("fail: %4d ", failures));
       sb.append("]");
       return sb.toString();
diff --git a/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/Benchmark.java b/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/Benchmark.java
index b589e92..71ae5ed 100644
--- a/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/Benchmark.java
+++ b/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/Benchmark.java
@@ -18,132 +18,152 @@
  */
 package org.apache.uima.fit.benchmark;
 
+import static java.util.Comparator.comparing;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.IntConsumer;
 import java.util.function.IntFunction;
 import java.util.function.LongSupplier;
 
-import org.apache.commons.lang3.StringUtils;
-
 public class Benchmark {
-    private IntConsumer initializer = t -> {};
-    private RunnableWithExceptions subject;
-    
-    private String name;
-    private int baseRepeat = 20;
-    private int repeatIncrementTimes;
-    
-    private int baseMagnitude = 1;
-    private int incrementTimes;
-    private IntFunction<Integer> magnitudeIncrement = t -> t;
-    private LongSupplier timer = () -> System.currentTimeMillis();
-    
-    private List<Batch> batches = new ArrayList<>();
-
-    public Benchmark(String aName, Benchmark aTemplate) {
-      name = aName;
-      
-      initializer = aTemplate.initializer;
-      subject = aTemplate.subject;
-      
-      baseRepeat = aTemplate.baseRepeat;
-      repeatIncrementTimes = aTemplate.repeatIncrementTimes;
-      
-      baseMagnitude = aTemplate.baseMagnitude;
-      incrementTimes = aTemplate.incrementTimes;
-      magnitudeIncrement = aTemplate.magnitudeIncrement;
-      timer = aTemplate.timer;
-    }
+	private IntConsumer initializer = t -> {
+	};
+	private RunnableWithExceptions subject;
 
-    public Benchmark(String aName) {
-      name = aName;
-    }
+	private final String name;
+	private int baseRepeat = 20;
+	private int repeatIncrementTimes;
 
-    public Benchmark timer(LongSupplier aTimer)
-    {
-      timer = aTimer;
-      return this;
-    }
+	private int baseMagnitude = 1;
+	private int incrementTimes;
+	private IntFunction<Integer> magnitudeIncrement = t -> t;
+	private LongSupplier timer = () -> System.currentTimeMillis();
 
-    public Benchmark repeat(int aRepeat)
-    {
-      baseRepeat = aRepeat;
-      return this;
-    }
+	private List<Batch> batches = new ArrayList<>();
 
-    public Benchmark magnitude(int aMagnitude)
-    {
-      baseMagnitude = aMagnitude;
-      return this;
-    }
+	public Benchmark(String aName, Benchmark aTemplate) {
+		name = aName;
 
-    public Benchmark magnitudeIncrement(IntFunction<Integer> aIncrement)
-    {
-      magnitudeIncrement = aIncrement;
-      return this;
-    }
+		initializer = aTemplate.initializer;
+		subject = aTemplate.subject;
 
-    public Benchmark incrementTimes(int aTimes)
-    {
-      incrementTimes = aTimes;
-      return this;
-    }
+		baseRepeat = aTemplate.baseRepeat;
+		repeatIncrementTimes = aTemplate.repeatIncrementTimes;
 
-    public Benchmark initialize(IntConsumer aPieceOfCode)
-    {
-      initializer = aPieceOfCode;
-      return this;
-    }
-    
-    public Benchmark measure(RunnableWithExceptions aPieceOfCode)
-    {
-      subject = aPieceOfCode;
-      return this;
+		baseMagnitude = aTemplate.baseMagnitude;
+		incrementTimes = aTemplate.incrementTimes;
+		magnitudeIncrement = aTemplate.magnitudeIncrement;
+		timer = aTemplate.timer;
+	}
+
+	public Benchmark(String aName) {
+		name = aName;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public Benchmark timer(LongSupplier aTimer) {
+		timer = aTimer;
+		return this;
+	}
+
+	public Benchmark repeat(int aRepeat) {
+		baseRepeat = aRepeat;
+		return this;
+	}
+
+	public Benchmark magnitude(int aMagnitude) {
+		baseMagnitude = aMagnitude;
+		return this;
+	}
+
+	public Benchmark magnitudeIncrement(IntFunction<Integer> aIncrement) {
+		magnitudeIncrement = aIncrement;
+		return this;
+	}
+
+	public Benchmark incrementTimes(int aTimes) {
+		incrementTimes = aTimes;
+		return this;
+	}
+
+	public Benchmark initialize(IntConsumer aPieceOfCode) {
+		initializer = aPieceOfCode;
+		return this;
+	}
+
+	public Benchmark measure(RunnableWithExceptions aPieceOfCode) {
+		subject = aPieceOfCode;
+		return this;
+	}
+
+	private Batch runBatch(int aMagnitude) {
+		Batch batch = new Batch(aMagnitude);
+
+		initializer.accept(aMagnitude);
+		for (int i = 0; i < baseRepeat; i++) {
+
+			long startTime = timer.getAsLong();
+			try {
+				subject.run();
+				batch.addMeasurement(new Measurement(i, timer.getAsLong() - startTime));
+			} catch (Exception e) {
+				batch.addMeasurement(new Measurement(i, timer.getAsLong() - startTime, e));
+			}
+		}
+
+		return batch;
+	}
+
+	public void run() {
+//		System.out.printf("%n%s%n", StringUtils.repeat("=", name.length()));
+		System.out.printf("%s: ", name);
+//		System.out.printf("%s%n", StringUtils.repeat("=", name.length()));
+
+		int magnitude = baseMagnitude;
+		int n = 0;
+
+		System.out.print("Running benchmark... ");
+		do {
+			if (magnitude > 0) {
+				System.out.printf("%d ", magnitude);
+			}
+			batches.add(runBatch(magnitude));
+			magnitude = magnitudeIncrement.apply(magnitude);
+			n++;
+		} while (n < incrementTimes);
+		System.out.printf("%n");
+
+//		for (Batch b : batches) {
+//			System.out.printf("%s%n", b);
+//		}
+	}
+
+	public List<Batch> getBatches() {
+		return batches;
+	}
+	
+    public long getMaxDuration() {
+      return getBatches().stream()
+          .flatMap(b -> b.getMeasurements().stream())
+          .max(comparing(Measurement::getDuration))
+          .get()
+          .getDuration();
     }
-    
-    private Batch runBatch(int aMagnitude)
-    {
-      Batch batch = new Batch(aMagnitude);
-      
-      initializer.accept(aMagnitude);
-      for (int i = 0; i < baseRepeat; i++) {
-        
-        long startTime = timer.getAsLong();
-        try {
-          subject.run();
-          batch.addMeasurement(new Measurement(i, timer.getAsLong() - startTime));
-        }
-        catch (Exception e) {
-          batch.addMeasurement(new Measurement(i, timer.getAsLong() - startTime, e));
-        }
-      }
-      
-      return batch;
+
+    public long getCumulativeDuration() {
+      return getBatches().stream()
+          .flatMap(b -> b.getMeasurements().stream())
+          .mapToLong(Measurement::getDuration).sum();
     }
-    
-    public void run()
-    {
-      System.out.printf("%n%s%n", StringUtils.repeat("=", name.length()));
-      System.out.printf("%s%n", name);
-      System.out.printf("%s%n", StringUtils.repeat("=", name.length()));
-      
-      int magnitude = baseMagnitude;
-      int n = 0;
-      
-      System.out.print("Running benchmark... ");
-      do {
-        if (magnitude > 0) {
-          System.out.printf("%d ", magnitude);
-        }
-        batches.add(runBatch(magnitude));
-        magnitude = magnitudeIncrement.apply(magnitude);
-        n++;
-      } while (n < incrementTimes);
-      System.out.printf("%n%n");
-      
-      for (Batch b : batches) {
-        System.out.printf("%s%n", b);
-      }
+
+    public Measurement getSlowestMeasurement() {
+      return getBatches().stream()
+          .flatMap(b -> b.getMeasurements().stream())
+          .max(comparing(Measurement::getDuration))
+          .get();
     }
   }
\ No newline at end of file
diff --git a/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/CasInitializationUtils.java b/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/CasInitializationUtils.java
index e9e53c2..72149bb 100644
--- a/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/CasInitializationUtils.java
+++ b/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/CasInitializationUtils.java
@@ -30,17 +30,15 @@ import org.apache.uima.fit.type.Token;
 
 public final class CasInitializationUtils
 {
-    private static final long RANDOM_SEED = 12345l;
-
     private CasInitializationUtils()
     {
         // No instances
     }
 
-    public static void initRandomCas(CAS cas, int size)
+    public static void initRandomCas(CAS cas, int size, long seed)
     {
         cas.reset();
-        Random rnd = new Random(RANDOM_SEED);
+        Random rnd = new Random(seed);
         List<Type> types = new ArrayList<Type>();
         types.add(cas.getTypeSystem().getType(Token.class.getName()));
         types.add(cas.getTypeSystem().getType(Sentence.class.getName()));
diff --git a/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/CasUtilBenchmark.java b/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/CasUtilBenchmark.java
index 52f2c6c..af827e0 100644
--- a/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/CasUtilBenchmark.java
+++ b/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/CasUtilBenchmark.java
@@ -18,6 +18,7 @@
  */
 package org.apache.uima.fit.benchmark;
 
+import static org.apache.uima.cas.text.AnnotationPredicates.overlapping;
 import static org.apache.uima.fit.benchmark.CasInitializationUtils.initRandomCas;
 import static org.apache.uima.fit.factory.TypeSystemDescriptionFactory.createTypeSystemDescription;
 import static org.apache.uima.fit.util.CasUtil.getType;
@@ -33,7 +34,6 @@ import static org.apache.uima.fit.util.CasUtil.selectOverlapping;
 import org.apache.uima.cas.CAS;
 import org.apache.uima.cas.Type;
 import org.apache.uima.cas.text.AnnotationFS;
-import org.apache.uima.fit.util.AnnotationPredicates;
 import org.apache.uima.util.CasCreationUtils;
 import org.junit.Before;
 import org.junit.Test;
@@ -41,6 +41,7 @@ import org.junit.Test;
 public class CasUtilBenchmark {
   private CAS cas;
   
+  private static final long RANDOM_SEED = 12345l;
   private static final String TYPE_NAME_TOKEN = "org.apache.uima.fit.type.Token";
   private static final String TYPE_NAME_SENTENCE = "org.apache.uima.fit.type.Sentence";
   
@@ -57,7 +58,7 @@ public class CasUtilBenchmark {
   @Test
   public void benchmarkSelect() {
     Benchmark template = new Benchmark("TEMPLATE")
-      .initialize(n -> initRandomCas(cas, n))
+      .initialize(n -> initRandomCas(cas, n, RANDOM_SEED))
       .magnitude(10)
       .magnitudeIncrement(count -> count * 10)
       .incrementTimes(5);
@@ -114,7 +115,7 @@ public class CasUtilBenchmark {
   @Test
   public void benchmarkSelectOverlapping() {
     Benchmark template = new Benchmark("TEMPLATE")
-        .initialize(n -> initRandomCas(cas, n))
+        .initialize(n -> initRandomCas(cas, n, RANDOM_SEED))
         .magnitude(10)
         .magnitudeIncrement(count -> count * 10)
         .incrementTimes(4);
@@ -132,7 +133,7 @@ public class CasUtilBenchmark {
         Type sentenceType = getType(cas, TYPE_NAME_SENTENCE);
         Type tokenType = getType(cas, TYPE_NAME_TOKEN);
         cas.select(sentenceType).forEach(s -> cas.select(tokenType)
-            .filter(t -> AnnotationPredicates.overlaps((AnnotationFS) t, (AnnotationFS)s))
+            .filter(t -> overlapping((AnnotationFS) t, (AnnotationFS)s))
             .forEach(t -> {}));
       })
       .run();
@@ -141,7 +142,7 @@ public class CasUtilBenchmark {
   @Test
   public void benchmarkSelectCovered() {
     Benchmark template = new Benchmark("TEMPLATE")
-        .initialize(n -> initRandomCas(cas, n))
+        .initialize(n -> initRandomCas(cas, n, RANDOM_SEED))
         .magnitude(10)
         .magnitudeIncrement(count -> count * 10)
         .incrementTimes(4);
@@ -171,7 +172,7 @@ public class CasUtilBenchmark {
   @Test
   public void benchmarkSelectCovering() {
     Benchmark template = new Benchmark("TEMPLATE")
-      .initialize(n -> initRandomCas(cas, n))
+      .initialize(n -> initRandomCas(cas, n, RANDOM_SEED))
       .magnitude(10)
       .magnitudeIncrement(count -> count * 10)
       .incrementTimes(3);
diff --git a/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/JCasUtilBenchmark.java b/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/JCasUtilBenchmark.java
index 303c125..2c2020f 100644
--- a/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/JCasUtilBenchmark.java
+++ b/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/JCasUtilBenchmark.java
@@ -18,176 +18,222 @@
  */
 package org.apache.uima.fit.benchmark;
 
-import static org.apache.uima.fit.benchmark.CasInitializationUtils.initRandomCas;
-import static org.apache.uima.fit.util.JCasUtil.selectOverlapping;
-import static org.apache.uima.fit.util.JCasUtil.indexCovered;
-import static org.apache.uima.fit.util.JCasUtil.indexCovering;
+import static org.apache.uima.cas.text.AnnotationPredicates.colocated;
+import static org.apache.uima.cas.text.AnnotationPredicates.coveredBy;
+import static org.apache.uima.cas.text.AnnotationPredicates.covering;
+import static org.apache.uima.cas.text.AnnotationPredicates.overlapping;
 import static org.apache.uima.fit.util.JCasUtil.select;
-import static org.apache.uima.fit.util.JCasUtil.selectAll;
 import static org.apache.uima.fit.util.JCasUtil.selectCovered;
 import static org.apache.uima.fit.util.JCasUtil.selectCovering;
+import static org.apache.uima.fit.util.JCasUtil.selectOverlapping;
 
-import org.apache.uima.fit.factory.JCasFactory;
 import org.apache.uima.fit.type.Sentence;
 import org.apache.uima.fit.type.Token;
-import org.apache.uima.fit.util.AnnotationPredicates;
-import org.apache.uima.jcas.JCas;
+import org.apache.uima.fit.util.JCasUtil;
 import org.apache.uima.jcas.cas.TOP;
-import org.junit.Before;
 import org.junit.Test;
 
 public class JCasUtilBenchmark {
-  private JCas jcas;
-  
-  @Before
-  public void setup() throws Exception {
-    if (jcas == null) {
-      jcas = JCasFactory.createJCas();
-    }
-    else {
-      jcas.reset();
-    }
-  }
-
   @Test
   public void benchmarkSelect() {
-    Benchmark template = new Benchmark("TEMPLATE")
-      .initialize(n -> initRandomCas(jcas.getCas(), n))
-      .magnitude(10)
-      .magnitudeIncrement(count -> count * 10)
-      .incrementTimes(5);
-    
-    new Benchmark("JCas select Token", template)
-      .measure(() -> select(jcas, Token.class))
-      .run();
-
-    new Benchmark("JCas select Token v3", template)
-      .measure(() -> jcas.select(Token.class))
-      .run();
+    CachingRandomJCasProvider casProvider = new CachingRandomJCasProvider();
 
-    new Benchmark("JCas select Token and iterate", template)
-      .measure(() -> select(jcas, Token.class).forEach(v -> {}))
-      .run();
-
-    new Benchmark("JCas select Token and iterate v3", template)
-      .measure(() -> jcas.select(Token.class).forEach(v -> {}))
-      .run();
-
-    new Benchmark("JCas select Sentence", template)
-      .measure(() -> select(jcas, Sentence.class))
-      .run();
-
-    new Benchmark("JCas select Sentence and iterate", template)
-      .measure(() -> select(jcas, Sentence.class).forEach(v -> {}))
-      .run();
+    Benchmark template = new Benchmark("TEMPLATE")
+        .initialize(casProvider::prepare)
+        .repeat(1_000)
+        .magnitude(10)
+        .magnitudeIncrement(count -> count * 10)
+        .incrementTimes(5);
     
-    new Benchmark("JCas select TOP", template)
-      .measure(() -> select(jcas, TOP.class))
-      .run();
+    new BenchmarkGroup("select")
+        .add(new Benchmark("WARM-UP", template)
+            .measure(() -> casProvider.get().select().forEach(t -> {})))
+        .add(new Benchmark("JCasUtil.selectAll(jcas).forEach(x -> {})", template)
+            .measure(() -> JCasUtil.selectAll(casProvider.get()).forEach(x -> {})))
+        .add(new Benchmark("jcas.select().forEach(x -> {})", template)
+            .measure(() -> casProvider.get().select().forEach(x -> {})))
+        .add(new Benchmark("JCasUtil.select(jcas, TOP.class).forEach(x -> {})", template)
+            .measure(() -> JCasUtil.select(casProvider.get(), TOP.class).forEach(x -> {})))
+        .add(new Benchmark("jcas.select(TOP.class).forEach(x -> {})", template)
+            .measure(() -> casProvider.get().select(TOP.class).forEach(x -> {})))
+        .add(new Benchmark("JCasUtil.select(jcas, Token.class).forEach(x -> {})", template)
+            .measure(() -> JCasUtil.select(casProvider.get(), Token.class).forEach(x -> {})))
+        .add(new Benchmark("jcas.select(Token.class).forEach(x -> {})", template)
+            .measure(() -> casProvider.get().select(Token.class).forEach(x -> {})))
+        .runAll();
+  }
 
-    new Benchmark("JCas select TOP and iterate", template)
-      .measure(() -> select(jcas, TOP.class).forEach(v -> {}))
-      .run();
+  @Test
+  public void benchmarkSelectOverlapping() {
+    CachingRandomJCasProvider casProvider = new CachingRandomJCasProvider();
     
-    new Benchmark("JCas select TOP and iterate v3", template)
-      .measure(() -> jcas.select(TOP.class).forEach(v -> {}))
-      .run();
-
-    new Benchmark("JCas select ALL", template)
-      .measure(() -> selectAll(jcas))
-      .run();
+    Benchmark template = new Benchmark("TEMPLATE")
+        .initialize(casProvider::prepare)
+        .repeat(25)
+        .magnitude(10)
+        .magnitudeIncrement(count -> count * 10)
+        .incrementTimes(3);
     
-    new Benchmark("JCas select ALL and iterate", template)
-      .measure(() -> selectAll(jcas).forEach(v -> {}))
-      .run();
-    new Benchmark("JCas select ALL and iterate v3", template)
-      .measure(() -> jcas.select().forEach(v -> {}))
-      .run();
+    new BenchmarkGroup("select overlapping")
+        .add(new Benchmark("WARM-UP", template)
+            .measure(() -> casProvider.get().select().forEach(t -> {})))
+        .add(new Benchmark("selectOverlapping(casProvider.get(), Token.class, s).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    selectOverlapping(Token.class, s).forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().select(Token.class).filter(t -> overlapping(t, s)).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().select(Token.class)
+                        .filter(t -> overlapping(t, s))
+                        .forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().getAnnotationIndex(Token.class).stream().filter(t -> overlapping(t, s)).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().getAnnotationIndex(Token.class).stream()
+                        .filter(t -> overlapping(t, s))
+                        .forEach(t -> {}));
+            }))
+        .runAll();
   }
   
   @Test
-  public void benchmarkSelectOverlapping() {
+  public void benchmarkSelectCoveredBy() {
+    CachingRandomJCasProvider casProvider = new CachingRandomJCasProvider();
+    
     Benchmark template = new Benchmark("TEMPLATE")
-      .initialize(n -> initRandomCas(jcas.getCas(), n))
-      .magnitude(10)
-      .magnitudeIncrement(count -> count * 10)
-      .incrementTimes(4);
+        .initialize(casProvider::prepare)
+        .repeat(25)
+        .magnitude(10)
+        .magnitudeIncrement(count -> count * 10)
+        .incrementTimes(3);
     
-    new Benchmark("CAS selectOverlapping", template)
-      .measure(() -> {
-        select(jcas, Sentence.class).forEach(s -> selectOverlapping(jcas, Token.class, s)
-            .forEach(t -> {}));
-      })
-      .run();
-
-    new Benchmark("CAS overlapping via index v3 (stream)", template)
-      .measure(() -> {
-        jcas.getAnnotationIndex(Sentence.class).forEach(s -> jcas.getAnnotationIndex(Token.class)
-            .stream()
-            .filter(t -> AnnotationPredicates.overlaps(t, s))
-            .forEach(t -> {}));
-      })
-      .run();
-
-    new Benchmark("CAS overlapping via index v3 (forEach)", template)
-      .measure(() -> {
-        jcas.getAnnotationIndex(Sentence.class).forEach(s -> jcas.getAnnotationIndex(Token.class)
-            .forEach(t -> AnnotationPredicates.overlaps(t, s)));
-      })
-      .run();
-
-    new Benchmark("CAS selectOverlapping v3", template)
-      .measure(() -> {
-        jcas.select(Sentence.class).forEach(s -> jcas.select(Token.class)
-            .filter(t -> AnnotationPredicates.overlaps(t, s))
-            .forEach(t -> {}));
-      })
-      .run();
+    new BenchmarkGroup("select covered by")
+        .add(new Benchmark("WARM-UP", template)
+            .measure(() -> casProvider.get().select().forEach(t -> {})))
+        .add(new Benchmark("selectCovered(Token.class, s).forEach(t -> {})", template)
+            .measure(() -> {
+              select(casProvider.get(), Sentence.class).forEach(s -> 
+                    selectCovered(Token.class, s).forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().select(Token.class).coveredBy(s).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().select(Token.class).coveredBy(s).forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().getAnnotationIndex(Token.class).select().coveredBy(s).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().getAnnotationIndex(Token.class).select().coveredBy(s).forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().select(Token.class).filter(t -> coveredBy(t, s)).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().select(Token.class)
+                        .filter(t -> coveredBy(t, s))
+                        .forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().getAnnotationIndex(Token.class).stream().filter(t -> coveredBy(t, s)).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().getAnnotationIndex(Token.class).stream()
+                        .filter(t -> coveredBy(t, s))
+                        .forEach(t -> {}));
+            }))
+        .runAll();
   }
   
   @Test
-  public void benchmarkSelectCovered() {
+  public void benchmarkSelectCovering() {
+    CachingRandomJCasProvider casProvider = new CachingRandomJCasProvider();
+    
     Benchmark template = new Benchmark("TEMPLATE")
-      .initialize(n -> initRandomCas(jcas.getCas(), n))
-      .magnitude(10)
-      .magnitudeIncrement(count -> count * 10)
-      .incrementTimes(4);
+        .initialize(casProvider::prepare)
+        .repeat(25)
+        .magnitude(10)
+        .magnitudeIncrement(count -> count * 10)
+        .incrementTimes(3);
     
-    new Benchmark("JCas selectCovered", template)
-      .measure(() -> select(jcas, Sentence.class).forEach(s -> selectCovered(Token.class, s)))
-      .run();
-
-    new Benchmark("JCas selectCovered v3", template)
-      .measure(() -> {
-          jcas.select(Sentence.class).forEach(s -> jcas.select(Token.class).coveredBy(s).forEach(t -> {}));
-      })
-    .run();
-
-    new Benchmark("JCas indexCovered", template)
-      .measure(() -> indexCovered(jcas, Sentence.class, Token.class).forEach((s, l) -> l.forEach(t -> {})))
-      .run();
+    new BenchmarkGroup("select covering")
+        .add(new Benchmark("WARM-UP", template)
+            .measure(() -> casProvider.get().select().forEach(t -> {})))
+        .add(new Benchmark("selectCovering(Token.class, s).forEach(t -> {})", template)
+            .measure(() -> {
+              select(casProvider.get(), Sentence.class).forEach(s -> 
+                    selectCovering(Token.class, s).forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().select(Token.class).covering(s).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().select(Token.class).covering(s).forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().getAnnotationIndex(Token.class).select().covering(s).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().getAnnotationIndex(Token.class).select().covering(s).forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().select(Token.class).filter(t -> covering(t, s)).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().select(Token.class)
+                        .filter(t -> covering(t, s))
+                        .forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().getAnnotationIndex(Token.class).stream().filter(t -> covering(t, s)).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().getAnnotationIndex(Token.class).stream()
+                        .filter(t -> covering(t, s))
+                        .forEach(t -> {}));
+            }))
+        .runAll();  
   }
   
   @Test
-  public void benchmarkSelectCovering() {
+  public void benchmarkSelectAt() {
+    CachingRandomJCasProvider casProvider = new CachingRandomJCasProvider();
+    
     Benchmark template = new Benchmark("TEMPLATE")
-      .initialize(n -> initRandomCas(jcas.getCas(), n))
-      .magnitude(10)
-      .magnitudeIncrement(count -> count * 10)
-      .incrementTimes(3);
+        .initialize(casProvider::prepare)
+        .repeat(25)
+        .magnitude(10)
+        .magnitudeIncrement(count -> count * 10)
+        .incrementTimes(3);
     
-    new Benchmark("JCas selectCovering", template)
-      .measure(() -> select(jcas, Token.class).forEach(t -> selectCovering(Sentence.class, t)))
-      .run();
-
-    new Benchmark("JCas selectCovering v3", template)
-      .measure(() -> {
-          jcas.select(Token.class).forEach(t -> jcas.select(Sentence.class).covering(t).forEach(s -> {}));
-      })
-    .run();
-
-    new Benchmark("JCas indexCovering", template)
-      .measure(() -> indexCovering(jcas, Token.class, Sentence.class).forEach((t, l) -> l.forEach(s -> {})))
-      .run();
+    new BenchmarkGroup("select at")
+        .add(new Benchmark("WARM-UP", template)
+            .measure(() -> casProvider.get().select().forEach(t -> {})))
+        .add(new Benchmark("JCasUtil.selectAt(casProvider.get(), Token.class, s.getBegin(), s.getEnd()).forEach(t -> {})", template)
+            .measure(() -> {
+              select(casProvider.get(), Sentence.class).forEach(s -> 
+                    JCasUtil.selectAt(casProvider.get(), Token.class, s.getBegin(), s.getEnd()).forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().select(Token.class).at(s.getBegin(), s.getEnd()).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().select(Token.class).at(s.getBegin(), s.getEnd()).forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().select(Token.class).at(s).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().select(Token.class).at(s).forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().select(Token.class).filter(t -> colocated(t, s)).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().select(Token.class)
+                        .filter(t -> colocated(t, s))
+                        .forEach(t -> {}));
+            }))
+        .add(new Benchmark("casProvider.get().getAnnotationIndex(Token.class).stream().filter(t -> colocated(t, s)).forEach(t -> {})", template)
+            .measure(() -> {
+                select(casProvider.get(), Sentence.class).forEach(s -> 
+                    casProvider.get().getAnnotationIndex(Token.class).stream()
+                        .filter(t -> colocated(t, s))
+                        .forEach(t -> {}));
+            }))
+        .runAll();  
   }
 }