0

We are looking to minimize (if not eliminate) object allocations in some high performance code. This was/is largely possible in previous versions of Chronicle Map (version 2.x). With the latest version of Chronicle Map (3.17.1) we seeing significant allocations when using ExternalMapQueryContext. We are following the tutorial here: https://github.com/OpenHFT/Chronicle-Map/blob/master/docs/CM_Tutorial.adoc

Is this expected? Are we using the proper approach?

VOInterface voi = VO.get();

try (ExternalMapQueryContext < CharSequence, voi, ? > ctx = map.queryContext(key)) {

    if (ctx.readLock().tryLock()) {
        MapEntry < CharSequence, voi > entry = ctx.entry();
        if (entry != null) {
            // Entry is present, return
            entry.value().getUsing(voi);
            accessor.accessData(voi);
            // Key is absent
            // Need to unlock, to lock to update lock later. Direct upgrade is forbidden.
            ctx.readLock().unlock();
            return true;
        } else {
            accessor.notFound();
            // Key is absent
            // Need to unlock, to lock to update lock later. Direct upgrade is forbidden.
            ctx.readLock().unlock();
            return false;
        }
    }

    ctx.updateLock().lock();
    MapEntry < CharSequence, voi > entry = ctx.entry();
    if (entry != null) {
        entry.value().getUsing(voi);
        accessor.accessData(voi);
        return true;
    } else {
        accessor.notFound();
        return false;
    }
}

We have screen grabs of the allocation stacks we can share as well.

Ömer Erden
  • 7,680
  • 5
  • 36
  • 45
  • The presented code itself shouldn't allocate at all. If it does, that's a bug, please report at https://github.com/OpenHFT/Chronicle-Map/issues. There might be a problem in `entry.value().getUsing(voi)`. It might read a CharSequence value into a new StringBuilder or a String and assign that into a `VOInterface`'s field. This might be due to a change in the logic in new version of [Chronicle Values](https://github.com/OpenHFT/Chronicle-Values). – leventov May 14 '19 at 18:12
  • Also, it looks like there is a bug in the code, because you needlessly do `ctx.readLock().unlock()` before `return true` and `return false`. The comments above the statements say "Need to unlock, to lock to update lock later", but that won't happen if you just return from the method. – leventov May 14 '19 at 18:14
  • I'm pretty sure the above code was taken almost verbatim from your tutorial docs ... has the recommended approach changed? If so, can you point towards best practice? – R. Prager Jun 05 '19 at 19:17
  • Yes, it looks like the code was originally copied from the tutorial docs, but then it was changed in a way that renders some parts of the code meaningless. There is no such problem in the examples in the tutorial. – leventov Jun 06 '19 at 13:12

1 Answers1

0

We have a test net.openhft.chronicle.map.ChronicleMapTest#testAcquireLockedPerf which performs millions of operations per second. You can run this with

-Xmx64m -verbose:gc

and for this situation, the test doesn't trigger a single gc, after warmup, for hundreds of millions of operations despite having 64 MB of heap.

To work out why your particular case creates significant garbage would take more investigation.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130