Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Take benefit of SQLite optimization when statement is cached vs when its used once or few time and finalized quickly #791

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

khanaffan
Copy link
Contributor

@khanaffan khanaffan commented Jun 18, 2024

Allow passing SQLITE_PREPARE_PERSISTENT to prepared statement when it is prepared with intention to be cached for multiple use.

The option avoid using lookaside memory which is use for shorter lived statement. lookaside memory allow faster prepare for single use query.

Also, note that for single-use statements, there is no guarantee of utilizing the lookaside memory pool if their state does not fit into a slot in the pool or if the pool has no empty slots. In such cases, it's allocated on the heap. By default, the lookaside memory is set to 48KB (40 slots of 1200 bytes), which is generally exhausted by cached statements. Allowing lookaside memory to be used by single-use statements can make single-use statement preparation, stepping, and finalization very fast and may not require any malloc at all.

With this change, we can prevent caching unnecessary SQLite statements and utilize single-use statements where appropriate, as they are faster to prepare and finalize compared to those allocated on the heap. The persistent flag will signal the query planner to allocate the statement on the heap when we intent to cache it.

Note: SQLite internally runs SQLite statements using either the execute or statement interface, which are also allocated on the heap. This occurs as the application has already exhausted 40 slots in the lookaside memory.

All of the following now use SQLITE_PREPARE_PERSISTENT option when preparing sqlite statement.

  • SqliteStatementCache
  • ECSqlStatementCache
  • ConcurrentQuery
  • InstanceQuery
  • TypeScript Sqlite/ECSql Statement caches

itwinjs-core: iTwin/itwinjs-core#6865

…its used once or few time and finalized quickly
@pmconne
Copy link
Member

pmconne commented Jun 18, 2024

/azp run imodel-native

@pmconne
Copy link
Member

pmconne commented Jun 19, 2024

faster to prepare and finalize

Did you measure actual meaningful performance improvements when querying an iModel?

IssueListener listener(*ecdb);

ECSqlStatus status = m_stmt.Prepare(*ecdb, ecsql.c_str(), logErrors);
ECSqlStatus status = m_stmt.Prepare(*ecdb, ecsql.c_str(), logErrors, persistent ? DbPrepareOptions::Persistent : DbPrepareOptions::None);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering here, in native we have the DbPrepareOptions (Persistent is the only option), but to typescript we expose just a boolean flag.
Why not do the same thing on both sides, it seems more intuitive. Do we expect there to be more options in the future? In that case an Options object seems correct. But if persistent remains the only option, a boolean flag seems better.

@khanaffan khanaffan marked this pull request as draft July 17, 2024 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants