class GroupingLongCollectorBenchmark {

    private GroupingCollector<?> groupBySumCollector;
    private List<Row> rows;
    private long[] numbers;
    private IndexSearcher searcher;

    @Setup
    public void createGroupingCollector() throws Exception {
        try (IndexWriter iw =
                 new IndexWriter(new ByteBuffersDirectory(), new IndexWriterConfig(new StandardAnalyzer()))) {
            Functions functions = Functions.load(Settings.EMPTY, new SessionSettingRegistry(Set.of()));
            SumAggregation<?> sumAgg = (SumAggregation<?>) functions.getQualified(
                Signature.aggregate(
                    SumAggregation.NAME,
                    DataTypes.INTEGER.getTypeSignature(),
                    DataTypes.LONG.getTypeSignature()
                ),
                List.of(DataTypes.INTEGER),
                DataTypes.INTEGER
            );
            var memoryManager = new OnHeapMemoryManager(bytes -> {
            });
            groupBySumCollector = createGroupBySumCollector(sumAgg, memoryManager);

            int size = 20_000_000;
            rows = new ArrayList<>(size);
            numbers = new long[size];
            for (int i = 0; i < size; i++) {
                long value = (long) i % 200;
                rows.add(new Row1(value));
                numbers[i] = value;
                var doc = new Document();
                doc.add(new NumericDocValuesField("x", value));
                doc.add(new SortedNumericDocValuesField("y", value));
                iw.addDocument(doc);
            }
            iw.commit();
            iw.forceMerge(1, true);
            searcher = new IndexSearcher(DirectoryReader.open(iw));
        }
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    private static GroupingCollector<?> createGroupBySumCollector(AggregationFunction<?, ?> sumAgg, MemoryManager memoryManager) {
        RowCollectExpression keyInput = new RowCollectExpression(0);
        List<Input<?>> keyInputs = List.of(keyInput);
        CollectExpression[] collectExpressions = new CollectExpression[]{keyInput};

        return GroupingCollector.singleKey(
            collectExpressions,
            AggregateMode.ITER_FINAL,
            new AggregationFunction[] { sumAgg },
            new Input[][] { new Input[] { keyInput }},
            new Input[] { Literal.BOOLEAN_TRUE },
            RamAccounting.NO_ACCOUNTING,
            memoryManager,
            Version.CURRENT,
            keyInputs.getFirst(),
            DataTypes.LONG,
            Version.CURRENT
        );
    }

    @Benchmark
    public void measureGroupBySumLong(Blackhole blackhole) throws Exception {
        var rowsIterator = InMemoryBatchIterator.of(rows, SENTINEL, true);
        blackhole.consume(rowsIterator.collect(groupBySumCollector).get());
    }

    @Benchmark
    public LongObjectHashMap<Long> measureGroupingOnNumericDocValues() throws Exception {<FILL_FUNCTION_BODY>}

    @Benchmark
    public LongObjectHashMap<Long> measureGroupingOnSortedNumericDocValues() throws Exception {
        var weight = searcher.createWeight(new MatchAllDocsQuery(), ScoreMode.COMPLETE_NO_SCORES, 1.0f);
        var leaf = searcher.getTopReaderContext().leaves().getFirst();
        var scorer = weight.scorer(leaf);
        var docValues = DocValues.getSortedNumeric(leaf.reader(), "y");
        var docIt = scorer.iterator();
        LongObjectHashMap<Long> sumByKey = new LongObjectHashMap<>();
        for (int docId = docIt.nextDoc(); docId != DocIdSetIterator.NO_MORE_DOCS; docId = docIt.nextDoc()) {
            if (docValues.advanceExact(docId)) {
                if (docValues.docValueCount() == 1) {
                    long number = docValues.nextValue();
                    sumByKey.compute(number, (key, oldValue) -> {
                        if (oldValue == null) {
                            return number;
                        } else {
                            return oldValue + number;
                        }
                    });
                }
            }
        }
        return sumByKey;
    }

    /**
     * To establish a base line on how fast it could go
     */
    @Benchmark
    public LongObjectHashMap<Long> measureGroupingOnLongArray() {
        LongObjectHashMap<Long> sumByKey = new LongObjectHashMap<>();
        for (long number : numbers) {
            sumByKey.compute(number, (key, oldValue) -> {
                if (oldValue == null) {
                    return number;
                } else {
                    return oldValue + number;
                }
            });
        }
        return sumByKey;
    }
}

        Weight weight = searcher.createWeight(new MatchAllDocsQuery(), ScoreMode.COMPLETE_NO_SCORES, 1.0f);
        LeafReaderContext leaf = searcher.getTopReaderContext().leaves().getFirst();
        Scorer scorer = weight.scorer(leaf);
        NumericDocValues docValues = DocValues.getNumeric(leaf.reader(), "x");
        DocIdSetIterator docIt = scorer.iterator();
        LongObjectHashMap<Long> sumByKey = new LongObjectHashMap<>();
        for (int docId = docIt.nextDoc(); docId != DocIdSetIterator.NO_MORE_DOCS; docId = docIt.nextDoc()) {
            if (docValues.advanceExact(docId)) {
                long number = docValues.longValue();
                sumByKey.compute(number, (key, oldValue) -> {
                    if (oldValue == null) {
                        return number;
                    } else {
                        return oldValue + number;
                    }
                });
            }
        }
        return sumByKey;
    
<no_super_class>