Higher memory consumption for prepared statements in FB3 --------------------------------------------------------
Key: CORE-5611 URL: http://tracker.firebirdsql.org/browse/CORE-5611 Project: Firebird Core Issue Type: Bug Components: Engine Affects Versions: 4.0 Alpha 1, 3.0.2, 3.0.1, 3.0.0, 4.0 Initial Reporter: Dmitry Yemanov Customer has reported about noticably higher memory consumption with FB 3.0 than they see with FB 2.5. This is somewhat expected, given the metadata cache is per-attachment in FB3 and their production database is complex. But then Paul Reeves and I were able to reproduce this with TPCC which database has just a few tables and procedures, so the metadata cache should not be a big issue. This is what I've got looking at mon$memory_usage (values are avg/max): v2.5 SS ----------- database: 22MB attachment: 150KB transaction: 1.7KB / 18KB statement: 25KB / 90KB v3.0 SS ----------- database: 160MB attachment: 2.4MB transaction: 1.1KB / 13KB statement: 88KB / 154KB Database counter is aggregated among all attachments, it doesnt show where the problem is, but it does show that the problem exists. Attachment counter clearly shows noticably higher memory usage, but we still cannot say for sure whether it's effect of the metadata caching or not. Transaction counter show only a little increase, it shouldn't be a problem. Finally, statement counter does indicate a problem. We see a 2x-3x more memory used for DSQL statements in v3.0 as compared to v2.5. Quick debugging shows that even trivial statements like "execute procedure X (A, B, C)" consume 3x more memory: 10KB vs 32KB (with the same impure size). Here are examples from the memory pool dumps for the same statements: v2.5 0x7ffff2b5e530 USED: size=80 allocated at ../src/jrd/par.cpp:686 0x7ffff2b5e5a0 USED: size=96 allocated at ../src/jrd/par.cpp:686 0x7ffff2b5e620 USED: size=80 allocated at ../src/jrd/par.cpp:686 0x7ffff2b5e690 USED: size=72 allocated at ../src/jrd/par.cpp:686 0x7ffff2b5e6f8 USED: size=80 allocated at ../src/jrd/par.cpp:686 0x7ffff2b5e768 USED: size=80 allocated at ../src/jrd/par.cpp:686 0x7ffff2b5e7d8 USED: size=80 allocated at ../src/jrd/par.cpp:686 0x7ffff2b5e848 USED: size=80 allocated at ../src/jrd/par.cpp:686 0x7ffff2b5e8b8 USED: size=72 allocated at ../src/jrd/par.cpp:686 0x7ffff2b5e920 USED: size=80 allocated at ../src/jrd/par.cpp:686 v3.0 USED 0x7fffe3405d20: size=56 allocated at /work/v3-release/src/jrd/../jrd/../jrd/../jrd/../dsql/Nodes.h:681 USED 0x7fffe3405d58: size=56 allocated at /work/v3-release/src/jrd/../jrd/../jrd/../jrd/../dsql/Nodes.h:681 USED 0x7fffe3405d90: size=56 allocated at /work/v3-release/src/jrd/../jrd/../common/classes/array.h:464 USED 0x7fffe3405dc8: size=232 allocated at /work/v3-release/src/jrd/par.cpp:1234 USED 0x7fffe3405eb0: size=56 allocated at /work/v3-release/src/jrd/../jrd/../jrd/../jrd/../dsql/Nodes.h:681 USED 0x7fffe3405ee8: size=56 allocated at /work/v3-release/src/jrd/../jrd/../jrd/../jrd/../dsql/Nodes.h:681 USED 0x7fffe3405f20: size=56 allocated at /work/v3-release/src/jrd/../jrd/../common/classes/array.h:464 USED 0x7fffe3405f58: size=232 allocated at /work/v3-release/src/dsql/ExprNodes.cpp:7783 USED 0x7fffe3406040: size=56 allocated at /work/v3-release/src/jrd/../jrd/../jrd/../jrd/../dsql/Nodes.h:681 USED 0x7fffe3406078: size=56 allocated at /work/v3-release/src/jrd/../jrd/../jrd/../jrd/../dsql/Nodes.h:681 USED 0x7fffe34060b0: size=56 allocated at /work/v3-release/src/jrd/../jrd/../common/classes/array.h:464 USED 0x7fffe34060e8: size=232 allocated at /work/v3-release/src/dsql/ExprNodes.cpp:7795 USED 0x7fffe34061d0: size=56 allocated at /work/v3-release/src/jrd/../jrd/../jrd/../jrd/../dsql/Nodes.h:681 USED 0x7fffe3406208: size=56 allocated at /work/v3-release/src/jrd/../jrd/../jrd/../jrd/../dsql/Nodes.h:681 USED 0x7fffe3406240: size=56 allocated at /work/v3-release/src/jrd/../jrd/../common/classes/array.h:464 USED 0x7fffe3406278: size=232 allocated at /work/v3-release/src/jrd/par.cpp:1230 USED 0x7fffe3406360: size=56 allocated at /work/v3-release/src/jrd/../jrd/../jrd/../jrd/../dsql/Nodes.h:681 USED 0x7fffe3406398: size=56 allocated at /work/v3-release/src/jrd/../jrd/../jrd/../jrd/../dsql/Nodes.h:681 USED 0x7fffe34063d0: size=56 allocated at /work/v3-release/src/jrd/../jrd/../common/classes/array.h:464 USED 0x7fffe3406408: size=232 allocated at /work/v3-release/src/jrd/par.cpp:1234 Besides the fact that the execution tree node itself is bigger in v3.0 (e.g. 232 vs 80 bytes), we also see 3 extra allocations by 56 bytes that didn't exist in v2.5. This makes a huge total difference. Given that the execution trees exist not only for DSQL statements but also for every cached PSQL object, this issue affects also the metadata cache thus making per-attachment memory usage even bigger. I can see several reasons: 1) Every node now contains vtable with a dozen of virtual methods 2) Nodes now contain both DSQL and JRD parts, even if one of them is unused 3) Child nodes are now wrapped in NodeRefImpl which is way too fat for a pointer wrapper (56 bytes due to its vtable) Item (1) is by design and supposedly cannot be fixed/improved. Regarding item (2): perhaps nodes could be spitted into two separate categories of objects (e.g. Dsql*Node, Jrd*Node), at least as a temporary solution, but this a big refactoring work which I'm afraid is not really suitable for v3 point releases. As for item (3), I'd suggest to rework this implementation. The current solution is designed with a type safety in mind, but the cost is just too high. Hopefully, some clever alternative could be invented instead. Or we'll have to live with a couple of unsafe casts. Additionally, I don't see where the DSQL parser tree is destroyed after being compiled into BLR. It's allocated out of the DSQL statement pool and seems to remain alive until the DSQL statement is freed and delete-by-pool happens. Do we really need to preserve the DSQL part of the tree? Or does it occupy memory for nothing and doubles the undesired memory overhead? This is not the v3 regression, but if we'd implement a way to clear unnecessary DSQL resources early, perhaps it could somewhat compensate the increased "by-design" part of the memory consumption. Adriano and others are welcome to share their opinions. We may change this ticket to "improvement" if necessary. -- This message is automatically generated by JIRA. - If you think it was sent incorrectly contact one of the administrators: http://tracker.firebirdsql.org/secure/Administrators.jspa - For more information on JIRA, see: http://www.atlassian.com/software/jira ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot Firebird-Devel mailing list, web interface at https://lists.sourceforge.net/lists/listinfo/firebird-devel