Feature #7366
improve performance of buffer.fill
80%
History
#1 Updated by Constantin Asofiei about 3 years ago
Created branch 7366a from trunk rev 14573.
7366a/14574 contains a first attempt at improving performance of Buffer.fill. This gives ~1% improvement for a large app.
- BEFORE-TABLE management - should direct record access be disabled in this case? If yes, check if BEFORE-TABLE can be handled explicitly.
- is the destination table in a
FILLoperation always a temp-table? If yes, then triggers can never be invoked. I'm not sure if other validation needs to be explicitly done. - replace Runnable lambdas with a Runnable instance and check performance (especially in
processDataSource).
#2 Updated by Constantin Asofiei about 3 years ago
- % Done changed from 0 to 80
7366a rev 14575 contains the changes for FILL performance improvements. Extent is not added yet.
#3 Updated by Ovidiu Maxiniuc about 3 years ago
Constantin Asofiei wrote:
Created branch 7366a from trunk rev 14573.
7366a/14574 contains a first attempt at improving performance of
The main takeways/unknowns are:Buffer.fill. This gives ~1% improvement for a large app.
- BEFORE-TABLE management - should direct record access be disabled in this case? If yes, check if BEFORE-TABLE can be handled explicitly.
Yes, I think this can use direct access. All BEFORE-TABLE-s have a single, non-unique index. And, as with the other temp-tables, they do not have triggers to fire.
- is the destination table in a
FILLoperation always a temp-table? If yes, then triggers can never be invoked. I'm not sure if other validation needs to be explicitly done.
Only temp-tables can be FILL-ed. In fact a temp-table must be first added to a dataset before this operation. The buffers of permanent tables cannot be components of a dataset.
I guess the only validation to be performed is null checking.
- replace Runnable lambdas with a Runnable instance and check performance (especially in
processDataSource).
Yes, extracting the independent lambdas as Runnable instance makes sense, but in my tests the gain is only 10% when the code to be executed is empty. Adding code to be executed will cause the gain to be unnoticeable.
#4 Updated by Constantin Asofiei about 3 years ago
Ovidiu, BEFORE-TABLE is not involved during FILL, as TRACKING-CHANGES is not allowed for FILL. So there is no need manage the BEFORE-TABLE records.
About null validation: how do you mark a temp-table field as non-null in 4GL? MANDATORY doesn't work.
#5 Updated by Ovidiu Maxiniuc about 3 years ago
I was pretty sure if you use
DEFINE TEMP-TABLE <name> LIKE <permanent-table-with-mandatory-fields> the mandatory attribute is preserved for the new fields.
However, this does not happens. The corresponding fields from the new temp-table will be able to store ? value. I googled it and there is the following kb article:
https://community.progress.com/s/article/Is-it-possible-to-make-a-temp-table-field-mandatory.
Actually, this is a good news. We can simplify the Validation.validateMaybeFlush() method for temp-tables.
#6 Updated by Constantin Asofiei about 3 years ago
rebased branch 7366a from trunk rev 14584 - new rev 14586.
#7 Updated by Constantin Asofiei about 3 years ago
Branch 7366a was merged to trunk rev 14589 and archived. What's left is a possible improvement for extent fields.
#8 Updated by Constantin Asofiei over 2 years ago
- the data-source query may or may not use all record fields, depending on the mapping. We can use the FIELDS option to force populating only those fields.
- try to create a FQL JOIN between the top and child buffer's data source queries, read all the records and cache them in a map on the 'join' condition.
#9 Updated by Constantin Asofiei about 2 years ago
Changes related to this are in 8363g rev 15158: Allow the query to be reset to its initialization state, so the same instance can be used to execute child buffer FILL operations.
#11 Updated by Constantin Asofiei about 2 years ago
Eric/Ovidiu: please review 8363g rev 15158.
#12 Updated by Ovidiu Maxiniuc about 2 years ago
Review of 8363g, r15157/8.
I think I understand the idea: if the same query can be reused for a child buffer, it does not make sense to recreate it for each iteration of the parent buffer. So instead of close/open, we so a clearResult() instead. There one thing I am not sure I fully understand: the optimization is active only when the fill() is called for the parent database. Why not use this when an individual buffer is called? For example, a top-level-buffer with one or multiple children?
I see no other issues with the new code.
#13 Updated by Constantin Asofiei about 2 years ago
Ovidiu Maxiniuc wrote:
I think I understand the idea: if the same query can be reused for a child buffer, it does not make sense to recreate it for each iteration of the parent buffer. So instead of close/open, we so a
clearResult()instead. There one thing I am not sure I fully understand: the optimization is active only when thefill()is called for the parent database. Why not use this when an individual buffer is called? For example, a top-level-buffer with one or multiple children?
You are right, I need to add a fillInt method to be called from the main Buffer.fill and for the child-buffer FILL in processDataSource. I'll see how I can change these.