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

fix(model-server): do not execute long-running repository operation on request threads #563

Merged
merged 4 commits into from
Mar 11, 2024

Conversation

odzhychko
Copy link
Contributor

Execute them on Dispatchers.IO because they are mostly blocked by waiting for data from store. Long-running operations are computeDelta and mergeChanges.

@odzhychko odzhychko requested a review from slisson as a code owner March 7, 2024 07:33
@odzhychko odzhychko marked this pull request as draft March 7, 2024 07:33
@odzhychko odzhychko force-pushed the fix/compute-delta-outside-request-thread branch from de7240f to 85297b9 Compare March 7, 2024 07:44
languitar
languitar previously approved these changes Mar 7, 2024
@odzhychko odzhychko marked this pull request as ready for review March 7, 2024 08:14
@odzhychko odzhychko force-pushed the fix/compute-delta-outside-request-thread branch from 85297b9 to 7cb2221 Compare March 7, 2024 10:08
Copy link
Member

@slisson slisson left a comment

Choose a reason for hiding this comment

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

The problematic cases are where a thread is blocked and not doing anything. If there are a lot of request that are blocked at the same location we need a lot of threads.

Using withContext(Dispatchers.IO) is not the best solution, because it just uses the unconstrained thread pool, but this still creates a lot of unnecessary threads. A better solution is to replace the blocking calls by coroutine features.

From the changes in this PR I identified the following problematic calls:


The transactions.txStart() call in IgniteStoreClient.runTransaction.

We can wrap that code with a Mutex to avoid trying to start a transaction while there is already an active one. This suspends the coroutine instead of blocking the thread.


The usage of lazy in RepositoriesManager.computeDelta.

This can be replaced by a Deferred data type and an async call.


Both changes will force you to make the methods, and all the transitive usages, suspendable. This automatically fixes all the locations where you now added withContext(Dispatchers.IO), which is then not required anymore.

I guess this also answers the question

On which level do we want to decide about execution (e.g. which thread pool to execute computation on)

We avoid blocking calls by using coroutine features. If not possible, we use withContext(Dispatchers.IO) around that call. The propagated suspend keyword automatically ensures that all HTTP endpoints are fixed.

@odzhychko odzhychko force-pushed the fix/compute-delta-outside-request-thread branch from 7cb2221 to f2f6c1b Compare March 8, 2024 07:51
@odzhychko odzhychko marked this pull request as draft March 8, 2024 07:55
@@ -283,71 +284,71 @@
return result
}

protected fun CallContext.putEntries(newEntries: Map<String, String?>) {
protected suspend fun CallContext.putEntries(newEntries: Map<String, String?>) {

Check warning

Code scanning / detekt

Prefer splitting up complex methods into smaller, easier to test methods. Warning

The function putEntries appears to be too complex based on Cyclomatic Complexity (complexity: 18). Defined complexity threshold for methods is set to '15'
@@ -283,71 +284,71 @@
return result
}

protected fun CallContext.putEntries(newEntries: Map<String, String?>) {
protected suspend fun CallContext.putEntries(newEntries: Map<String, String?>) {

Check warning

Code scanning / detekt

Excessive nesting leads to hidden complexity. Prefer extracting code to make it easier to understand. Warning

Function putEntries is nested too deeply.
Execute non suspendable part outside request threads.
@odzhychko odzhychko force-pushed the fix/compute-delta-outside-request-thread branch from 50c3e8a to 9751444 Compare March 8, 2024 09:37
private val LOG = LoggerFactory.getLogger(VersionDeltaCache::class.java)
}

private val cacheMap = LRUMap<Pair<String, String?>, SoftReference<Deferred<ObjectDataMap>>>(10)

Check warning

Code scanning / detekt

This expression contains a magic number. Consider defining it to a well named constant. Warning

This expression contains a magic number. Consider defining it to a well named constant.
@odzhychko odzhychko marked this pull request as ready for review March 8, 2024 10:07
@odzhychko odzhychko requested a review from slisson March 8, 2024 10:07
…pendable transactions

This avoids blocking one additional thread.
@odzhychko odzhychko force-pushed the fix/compute-delta-outside-request-thread branch from 9751444 to 79af748 Compare March 11, 2024 11:24
@odzhychko odzhychko enabled auto-merge March 11, 2024 11:29
@odzhychko odzhychko merged commit 45f7d53 into main Mar 11, 2024
13 checks passed
@odzhychko odzhychko deleted the fix/compute-delta-outside-request-thread branch March 11, 2024 11:33
@slisson
Copy link
Member

slisson commented Mar 11, 2024

🎉 This PR is included in version 5.1.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants