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: Limit default ThreadPoolExecutor thread count and remove deadlock scenario #985

Merged
merged 5 commits into from
Aug 30, 2024

Conversation

jonathanedey
Copy link
Contributor

  • The default thread manger now limits to 100 threads. This resolves OOM errors that come with threads used to send large amounts of FCM messages.
  • Deadlock scenario in sendEachAsync() and sendEachForMulticastAsync() is now avoided by chaining ApiFutures

Copy link
Member

@lahirumaramba lahirumaramba left a comment

Choose a reason for hiding this comment

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

Thanks Jonathan!
Overall looks good to me, added a few comments

@@ -84,7 +84,8 @@ private static class DefaultThreadManager extends GlobalThreadManager {
protected ExecutorService doInit() {
ThreadFactory threadFactory = FirebaseScheduledExecutor.getThreadFactoryWithName(
getThreadFactory(), "firebase-default-%d");
return Executors.newCachedThreadPool(threadFactory);

return Executors.newFixedThreadPool(100, threadFactory);
}
Copy link
Member

Choose a reason for hiding this comment

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

Since a cached thread pool is preferred for short lived tasks, could this introduce any potential performance issues?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes the downside of the this is that threads once created aren't closed until shutdown.

Made a change to add a keepAliveTime for idle threads so this would no longer be the case. I was missing the allowCoreThreadTimeOut() method in testing which allows the timer to be applied.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks! This LGTM!

}

private CallableOperation<BatchResponse, FirebaseMessagingException> sendEachOp(
private ApiFuture<BatchResponse> sendEachOpAsync(
Copy link
Member

Choose a reason for hiding this comment

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

This LGTM, but since this more of the opposite of how the rest of the SDK implements async operations, could we add a comment in code or in this thread briefly explaining this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added!

@@ -84,7 +84,8 @@ private static class DefaultThreadManager extends GlobalThreadManager {
protected ExecutorService doInit() {
ThreadFactory threadFactory = FirebaseScheduledExecutor.getThreadFactoryWithName(
getThreadFactory(), "firebase-default-%d");
return Executors.newCachedThreadPool(threadFactory);

return Executors.newFixedThreadPool(100, threadFactory);
}
Copy link
Member

Choose a reason for hiding this comment

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

Thanks! This LGTM!

@jonathanedey jonathanedey merged commit 797a8af into master Aug 30, 2024
6 checks passed
@jonathanedey jonathanedey deleted the je-threads branch August 30, 2024 18:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release:stage Stage a release candidate release-note
Projects
None yet
Development

Successfully merging this pull request may close these issues.

FirebaseMessaging sendEachAsync(), sendEachForMulticastAsync() can cause thread deadlock
2 participants