Are those optimizations for all ObjectContexts, not just the app-scoped single context used by many threads that you mentioned?
On Mon, Oct 12, 2026 at 7:15 PM Andrus Adamchik <[email protected]> wrote: > And there are more select optimizations. All the CPU time savings below > are "the Cayenne part of a select query" : > > * https://issues.apache.org/jira/browse/CAY-3049 Faster, lower-overhead > LRU snapshot cache. Saves 40-60% CPU time on plain selects, 20-45% with > prefetches. > * https://issues.apache.org/jira/browse/CAY-3050 [STILL IN PROGRESS, but > almost ready] Faster. Saves 30-40% CPU time on plain selects, 20-40% with > prefetches. 25-30% less memory allocation. > * https://issues.apache.org/jira/browse/CAY-3051 somewhat lower memory > allocation overhead > > The numbers almost look too good to be true :) But good data structures go > a long way. I will be checking this in a real application soon, and would > love an independent confirmation once CAY-3050 makes it in. > > Andrus > > > On Oct 11, 2026, at 6:34 PM, Andrus Adamchik <[email protected]> > wrote: > > > > Hi, > > > > Just pushed a couple of big improvements to DataContext read > concurrency. Related jiras: CAY-3044, CAY-3045, CAY-3046, CAY-3047, > CAY-3048. > > > > Consider a single DataContext used by many threads in parallel for > selecting objects. I have a number of very active read-only apps, and an > app-scoped DataContext has always been the default pattern, especially > valuable with local cache. It works great until concurrency increases > causing every single select to queue up on ObjectStore waiting to load its > rows into the context. > > > > So there was a de-facto hard cap on context throughput. Previously, I > solved this via context pooling. This is ugly and luckily is no longer > needed in this release. In my benchmarks, throughput improved 2x. This > number will vary depending on the connection pool, CPU, DB speed of course. > But lock contention is gone and the new usage advice is: > > > > 1. If you DON'T use local cache, then a new DataContext per thread (= > per request) is the most performant option. > > 2. If you DO use local cache (or want to keep such option open for the > future; or don't want to deal with per-request scope), use a shared > DataContext and don't worry about locking. This option is slightly (~5%) > slower than a per-thread context, but this is negligible. > > > > Before the release, I would appreciate if someone could try it out and > report any issues. The changes touch on the object / snapshot consistency > model. So if you see anything weird, like older versions of objects > appearing after newer ones, please report. (To be clear, I don't expect > this to happen :)) > > > > > > --- > > > > Finally, some high-level technical details. You can stop reading here :) > > > > * Instead of broad per-select lock to load objects, the locking is done > per object, using private "striped" locks. I was surprised using > "synchronized" in a loop (on different monitors) is not slow. But > apparently it is fast with modern Java. > > * ObjectContext / ObjectStore object lookups are not synchronized anymore > > * Eventual consistency of object states is ensured by per-object locks > and incrementing snapshot versions. We had snap versions before, but now > they are faster, smarter and actually help. > > * Merge strategy fix to avoid excessive to-one faulting post-query. I > was occasionally confused seeing objects fetched one-by-one right after > they were fetched by another query prefetch. Thought this was due to weak > references. Nope, just faulty merge logic + concurrency. > > * Per-statement snapshot versions (instead of per-object) > > * Safer fault checking to avoid a specific race condition causing > ClassCastExceptions under load > > > > > > Andrus > >
