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 #6865

Open
wants to merge 6 commits into
base: master
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

We should also name the IModelDb.withPreparedStatement() as IModelDb.withCachedStatement() while keep same name for IModelDb.withStatement(). Thought this not part of this PR.

imodel-native: iTwin/imodel-native#791

@khanaffan khanaffan marked this pull request as ready for review June 18, 2024 22:14
@khanaffan khanaffan requested a review from a team as a code owner June 18, 2024 22:14
prepareSqliteStatement(sql: string, logErrors?: boolean): SqliteStatement;
prepareStatement(sql: string, logErrors?: boolean): ECSqlStatement;
prepareSqliteStatement(sql: string, logErrors?: boolean, persistent?: boolean): SqliteStatement;
prepareStatement(sql: string, logErrors?: boolean, persistent?: boolean): ECSqlStatement;
Copy link
Member

Choose a reason for hiding this comment

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

Please prefer not to add new optional arguments. Consider instead adding an overload that takes a single args object.

Copy link
Contributor

mergify bot commented Jul 1, 2024

This pull request is now in conflicts. Could you fix it @khanaffan? 🙏
To fixup this pull request, you can check out it locally. See documentation: https://help.github.com/articles/checking-out-pull-requests-locally/

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.

None yet

2 participants