-
Notifications
You must be signed in to change notification settings - Fork 148
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
feat: allow specifying how many idle GRPC channels to keep #837
Conversation
d8ae845
to
8d94521
Compare
Codecov Report
@@ Coverage Diff @@
## master #837 +/- ##
==========================================
- Coverage 88.83% 88.82% -0.01%
==========================================
Files 27 27
Lines 16725 16765 +40
Branches 1151 1156 +5
==========================================
+ Hits 14858 14892 +34
- Misses 1862 1868 +6
Partials 5 5
Continue to review full report at Codecov.
|
bb88a59
to
470e450
Compare
470e450
to
e3d7882
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly nits...
As an aside, I will just point out that it seems unfortunate that we have to expose this to developers and make them make a trade-off between latency, memory, and the ability for the client to 100% shut down (if I'm understanding correctly). I worry that the only way people will find out about this options is when they run into some problem, diagnose it, and then go googling for it and find a post telling them to change this. That means many people will just suffer through the problem (because googling / solving problems is hard) and those that do solve it will have had to go on an unwanted adventure to diagnose / solve the problem.
All that is to say: We should do our best to make this "just work" for as many use cases as possible so 99.9% of people don't need to go on this adventure. :-)
dev/src/pool.ts
Outdated
this.activeClients.forEach((requestCount, client) => { | ||
if (!selectedClient && requestCount < this.concurrentOperationLimit) { | ||
for (const [client, requestCount] of this.activeClients) { | ||
// Bin pack requests to reduce the maximize the number of idle clients as |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"reduce the maximize the ..."? Also, I don't do bin packing enough for this comment to 100% make sense right away. And I had to think more than 3 seconds to figure out what "selectedRequestCount" was.
Perhaps rename selectedRequestCount to selectedClientRequestCount (long/verbose, I know, sorry!) and the comment to something like:
Use the "most-full" client that can still accommodate the required requestCount in order to maximize the number of idle clients as operations start to complete.
Don't feel very strongly though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your comment is not only grammatically correct, but also more helpful. Thanks!
@@ -77,7 +85,7 @@ export class ClientPool<T> { | |||
selectedClient = client; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The log line above is going to get spewed multiple times now. I think it should be extracted from the for-loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. I moved it outside the loop.
dev/src/pool.ts
Outdated
assert(requestCount > 0, 'No active request'); | ||
this.activeClients.set(client, requestCount! - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems odd you need the !
but I assume you have your reasons...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uhm. I hope I had my reasons when I added it first, but they are not immediately apparent now. Removed.
dev/src/pool.ts
Outdated
// least one active client as a single client can never exceed the | ||
// concurrent operation limit by itself). | ||
// - Use `maxIdleClients:0` to shut down the client pool completely when all | ||
// clients are idle. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I read this comment 2 or 3 times, and read the code once, and the code still makes more sense to me than the comment. So it might be worth rephrasing / paring down the comment. I'm not 100% sure what it's trying to get across. Is it justifying the existence of the maxIdleClients setting (in which maybe the bulk of this comment should go there?)? Or is there actually some nuance to this code that needs 10 lines of explanation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to justify that the code doesn't just count the number of idle clients, but instead counts the number of idle "request slots". If this comment doesn't help, then I am ok with removing it.
dev/src/types.ts
Outdated
/** | ||
* The maximum number of idle GRPC channels to keep. A smaller number of idle | ||
* channels reduces memory usage but increases request latency for clients | ||
* with fluctuating request rates. Defaults to 1. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Elsewhere you document that setting it to 0 allows the client pool to shut down completely. Is that a behavior that should be documented here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good suggestion. Added (here and in the other two places...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your review. There was no rush for this :)
The default setting should keep the existing behavior and work for most users. There have been a couple complaints about our memory usage from very heavy users. I don't expect maxIdleChannels
to be an often used setting, but it should allow users that want to tune memory usage to do so.
dev/src/pool.ts
Outdated
this.activeClients.forEach((requestCount, client) => { | ||
if (!selectedClient && requestCount < this.concurrentOperationLimit) { | ||
for (const [client, requestCount] of this.activeClients) { | ||
// Bin pack requests to reduce the maximize the number of idle clients as |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your comment is not only grammatically correct, but also more helpful. Thanks!
@@ -77,7 +85,7 @@ export class ClientPool<T> { | |||
selectedClient = client; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. I moved it outside the loop.
dev/src/pool.ts
Outdated
assert(requestCount > 0, 'No active request'); | ||
this.activeClients.set(client, requestCount! - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uhm. I hope I had my reasons when I added it first, but they are not immediately apparent now. Removed.
dev/src/pool.ts
Outdated
// least one active client as a single client can never exceed the | ||
// concurrent operation limit by itself). | ||
// - Use `maxIdleClients:0` to shut down the client pool completely when all | ||
// clients are idle. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to justify that the code doesn't just count the number of idle clients, but instead counts the number of idle "request slots". If this comment doesn't help, then I am ok with removing it.
dev/src/types.ts
Outdated
/** | ||
* The maximum number of idle GRPC channels to keep. A smaller number of idle | ||
* channels reduces memory usage but increases request latency for clients | ||
* with fluctuating request rates. Defaults to 1. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good suggestion. Added (here and in the other two places...)
This PR lets users influence the memory profile of their Firestore usage:
This PR aims to preserve the current behavior by always leaving at least one GRPC channel if no option is provided.
b/146363799