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:48 UTC

[uima-uimafit] branch feature/UIMA-6291-Improve-uimaFIT-benchmarking-module created (now fc06d67)

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

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


      at fc06d67  [UIMA-6291] Improve uimaFIT benchmarking module

This branch includes the following new commits:

     new fc06d67  [UIMA-6291] Improve uimaFIT benchmarking module

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



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

Posted by re...@apache.org.
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();  
   }
 }