private double benchmarkIterations(RankingExpression gbdt, Context contextPrototype,
                                       List<Map<String, Double>> features, int iterations) {
        // Simulate realistic use: The array context can be reused for a series of evaluations in a thread
        // but each evaluation binds a new set of values.
        double total=0;
        Context context = copyForEvaluation(contextPrototype);
        long totalNanoTime = 0;
        for (int i=0; i<iterations; i++) {
            for (Map<String, Double> featureItem : features) {
                long startTime = System.nanoTime();
                bindStreamingFeatures(featureItem, context);
                total += gbdt.evaluate(context).asDouble();
                totalNanoTime += System.nanoTime() - startTime;
                blowCaches();
            }
        }
        System.out.println("Total time fine-grain measured: " + totalNanoTime/(1000 * iterations * features.size()));
        return total;
    }
Read an ad-hoc file format with some similarly ad hoc code
searchlib/src/test/java/com/yahoo/searchlib/rankingexpression/evaluation/StreamEvaluationBenchmark.java