Support #4032
block/transaction processing context-local and other performance improvements
0%
Related issues
History
#1 Updated by Greg Shah over 7 years ago
From Constantin:
TransactionManager is also used in most of the scopeStart/scopeFinished (Scopeables) notifications, to check the current block's type; we should improve those, too.
We could potentially pass the TransactionHelper instance as part of the notification.
#2 Updated by Greg Shah over 7 years ago
- Subject changed from block/transaction processing performance improvements to block/transaction processing context-local and other performance improvements
From Eric:
ProcedureManager.hasReferent is showing as a minor bottleneck in a particular case, due to its ContextLocal use and the fact that it is invoked almost 400k times from handle._isValid (mostly calls from LogicalTerminal.getChanges).
In LT.getChanges, we iterate the entire frameRegistry map on each call, which is how we get so many calls to handle._isValid. Is this necessary, or is there an "active" subset of frames that actually matter?
#3 Updated by Greg Shah about 7 years ago
ErrorManager should be moved to a TransactionHelper design. For example, ErrorManager.isPendingError() is very expensive and is often used.
LE: see #4828.
#4 Updated by Greg Shah about 7 years ago
Constantin: To what extent do we need to look at additional optimizations in ControlFlowOps and ProcedureManager? The way I recall it, some quick things were done recently but it may deserve a more serious look.
#5 Updated by Greg Shah about 7 years ago
From Eric (see #3992-159):
We could save a little bit of time by streamlining HandleOps.getLegacyAnnotation. This method uses introspection to pull out an annotation. This is fine once, but the information is lost after return and subsequent calls must do all the introspection over again. Seems like this information should be cached, but I'm not sure to what a cache would be attached and what exactly the key would be.
#6 Updated by Greg Shah about 7 years ago
From Eric (see #3992-162):
ProcedureManager.hasReferent is showing as a minor bottleneck in some use cases, due to its
ContextLocaluse and the fact that it is invoked hundreds of thousands of times fromhandle._isValid()(mostly calls fromLogicalTerminal.getChanges()).
#7 Updated by Greg Shah about 7 years ago
From Eric in #3992-163:
SourceNameMapper.removePkg()is called hundreds of thousands of times in some use cases, throughProcedureManager.getName(). Most of those come fromControlFlowOps$InternalResolver.resolve().The combination of
String.startsWith()andString.substring()inremovePkg()is what makes this a minor bottleneck.
From Eric in #3992-164:
Although we improved
SourceNameMapper$ExternalProgram.search()already (#3992-94), it is still a minor bottleneck, due to lowercasing the legacy name in the InternalEntryKey c'tor. I normalized the keys to use a lowercase legacy name because the old search algorithm did an equalsIgnoreCase comparison. Is this strictly necessary? Is it possible for the search values being passed in to be of inconsistent case? They are coming from RUN statements in 4GL code, right? Which I guess means they could be any case on Windows. If that's true, then there's not much more we can do to improve this search's performance, AFAICT.
#8 Updated by Constantin Asofiei about 7 years ago
Greg Shah wrote:
Constantin: To what extent do we need to look at additional optimizations in
ControlFlowOpsandProcedureManager? The way I recall it, some quick things were done recently but it may deserve a more serious look.
Actually I did a pretty thorough replacement of the direct access with the helper approach, for these two files. If anything else would stick out during profiling, we can address them then.
#9 Updated by Greg Shah over 6 years ago
I've documented some ideas related to Constantin's CFS reflection optimization task (#1970).
#10 Updated by Greg Shah over 6 years ago
- Related to Feature #1970: improve ControlFlowOps method resolution by reflection added
#11 Updated by Greg Shah over 5 years ago
During work on some transaction processing issues, we've seen that we are providing notifications for a range of services in blocks that are marked as BlockManager.TransactionType.NONE/TransactionManager.NO_TRANSACTION. For example, you can register as a Finalizable, Commitable or Undoable even in a NO_TRANSACTION block AND WE WILL DELIVER ALL NOTIFICATIONS! Likewise all the Scopable notifications occur for NO_TRANSACTION blocks. As far as I know, there ARE NO transaction/block properties for such blocks. I think we should carefully review this code and test to see if there is any real reason that we need to notify in these cases. Any registrations probably should be in the nearest containing SUB_TRANSACTION or FULL_TRANSACTION.
In addition to doing a lot of extra work, we may even be incorrectly processing those blocks.
From Constantin on a related note:
I want to expand this a little, as you remind me of something (which maybe I mentioned before, but I don't recall). In profiling this doesn't appear (but I haven't profiled them explicitly lately), there is other unnecessary scope start/finished work for scopeables. Take AccumulatorManager for example - this will be notified of each and every scope, even if accumulator usage is maybe not even 10% of the application.
I was thinking maybe there is some way to 'lazy initialize' some of the scopeables and activate them only when they are needed. But, as I mentioned, I don't have a cost/benefit analysis in terms of application performance impact of these.
#12 Updated by Greg Shah over 5 years ago
I had previously created the NO_TRANSACTION task in #4149.
#13 Updated by Greg Shah over 5 years ago
- Related to Bug #4149: BlockManager and TransactionManager handle TransactionType.NONE incorrectly added
#14 Updated by Constantin Asofiei over 3 years ago
- File ContextLocalGetTraces.ods added
Attached is a trace file with ContextLocal.get usage in a customer application. This is expanded on 3 levels, level 1 being root (ContextLocal.get()) and level 2 being bold to be easier found.
- I solved the top callers of
UniqueIdGenerator.getUniqueIdby lazily computing this UNIQUE-ID value; I don't see any reason why we should have this pre-computed if the application never calls it. There is a place in AbstractTempTable where for some reason a null UNIQUE-ID is expected - but I can't figure out why - I have some changes in TableMapper which somehow reduces the
ContextLocal.getcalls, but there is some other refactoring required on this, I'll post more notes at #6825 - I think I'll do some experimenting if keeping the reference of
ProcedureManager$ProcedureHelper(and maybe others) at theHandleResourceinstance will help - this way we would have direct access to it. Another related point would be to have theObjectOps$WorkAreainstance at theobjectinstance.
#15 Updated by Constantin Asofiei over 3 years ago
Constantin Asofiei wrote:
- I think I'll do some experimenting if keeping the reference of
ProcedureManager$ProcedureHelper(and maybe others) at theHandleResourceinstance will help - this way we would have direct access to it. Another related point would be to have theObjectOps$WorkAreainstance at theobjectinstance.
This seems to pay off in performance testing a large app. But a good portion (30%) is still from AnnotatedAst/TRPL usage.
#16 Updated by Constantin Asofiei over 3 years ago
A batch of changes (including #4032-5) are in 6129b/14349
#17 Updated by Constantin Asofiei over 3 years ago
Another batch of changes related to this is in 6129b/14366
#18 Updated by Constantin Asofiei over 3 years ago
- cache the 'helper' instance at the WrappedResource, object and other cases, to avoid resolving the ContextLocal instance on each access.
- use some other approaches (like delay calculation for UNIQUE-ID) to reduce the number of ContextLocal.get calls
But, 50% of the 15m calls in a large application is from TRPL processing (AstSymbolResolver.getResolver()). This requires some re-thinking of the TRPL engine for dynamic query/temp-table conversion - as currently the state is kept in each context, but the TRPL rule-sets are in a JVM singleton mode, and not context-local.
In ContextLocal.get terms, the completion can be considered at 90%, as what remains is AstSymbolResolver.getResolver()
#19 Updated by Constantin Asofiei almost 3 years ago
4032a was created from trunk rev 14668.
4032a rev 14669 contains another batch of context-local improvements.
#20 Updated by Greg Shah almost 3 years ago
Code Review Task Branch 4032a Revisions 14680 through 14682
The changes look good. They also seem fairly low risk.
#21 Updated by Greg Shah almost 3 years ago
Please merge 4032a to trunk.
#22 Updated by Constantin Asofiei almost 3 years ago
Branch 4032a was merged to trunk rev 14689 and archived.
I've created 4032b from trunk rev 14689 where there will be some other changes.
#24 Updated by Constantin Asofiei almost 3 years ago
4032b was rebased from trunk rev 14721.
4032b rev 14722 contains a small batch of performance improvements related to context-local usage for OUTPUT parameters and object, plus basic for loop iteration for 'finalizables'.