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

Add a connection pool manager #1189

Merged
merged 8 commits into from
Jun 1, 2021
Merged

Add a connection pool manager #1189

merged 8 commits into from
Jun 1, 2021

Conversation

glbrntt
Copy link
Collaborator

@glbrntt glbrntt commented May 21, 2021

Motivation:

In #1176 we added a per-event-loop connection pool. In order to make a
client which uses these pools we need a way to manage them. This PR adds
a connection pool manager.

Modifications:

  • Add a pool manager state machine which tracks connection pools and
    per-pool state such as the number of streams available and reserved
    for each pool.
  • Add a pool manager which wraps the state machine.
  • Add a pool manager state machine tests; the pool manager isn't tested
    here but will be tested indirectly in a later PR (when a client is
    added to wrap the pool manager).

Result:

We can manage connection pools.

@glbrntt glbrntt added the 🔨 semver/patch No public API change. label May 21, 2021
@glbrntt glbrntt requested a review from Lukasa May 21, 2021 09:22
@glbrntt
Copy link
Collaborator Author

glbrntt commented May 21, 2021

cc @fabianfett

Motivation:

In grpc#1176 we added a per-event-loop connection pool. In order to make a
client which uses these pools we need a way to manage them. This PR adds
a connection pool manager.

Modifications:

- Add a pool manager state machine which tracks connection pools and
  per-pool state such as the number of streams available and reserved
  for each pool.
- Add a pool manager which wraps the state machine.
- Add a pool manager state machine tests; the pool manager isn't tested
  here but will be tested indirectly in a later PR (when a client is
  added to wrap the pool manager).

Result:

We can manage connection pools.
@glbrntt glbrntt force-pushed the gb-pool-manager branch from a821514 to c23453d Compare May 21, 2021 10:12
Copy link
Collaborator

@fabianfett fabianfett left a comment

Choose a reason for hiding this comment

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

Some nits and room for one discussion.

Sources/GRPC/ConnectionPool/PoolManager.swift Outdated Show resolved Hide resolved
Sources/GRPC/ConnectionPool/PoolManager.swift Outdated Show resolved Hide resolved
Comment on lines 257 to 261
internal func increaseStreamCapacity(by delta: Int, for pool: ConnectionPool) {
self.lock.withLockVoid {
self.state.increaseStreamCapacity(by: delta, for: pool)
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could a streams capacity also be decreased?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, a negative delta is acceptable here. I'll change this to changeStreamCapacity.

Sources/GRPC/ConnectionPool/PoolManager.swift Outdated Show resolved Hide resolved
Sources/GRPC/ConnectionPool/PoolManager.swift Show resolved Hide resolved
Sources/GRPC/ConnectionPool/PoolManager.swift Outdated Show resolved Hide resolved
@glbrntt glbrntt requested a review from Lukasa May 26, 2021 09:27

// The state machine stores the per-pool state keyed by the pools `EventLoopID` and tells the
// pool manager about which pool to use/operate via the pools index in `self.pools`.
let poolKeys = self.pools.enumerated().map { poolIndex, pool in
Copy link
Collaborator

Choose a reason for hiding this comment

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

A minor defensiveness note: poolIndex is an index only if the stored data type is Array. Otherwise, enumerated does offsets, not indices. It may be better to rename this, or to provide an alternative implementation that actually does use indices and not offsets.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Great point; I appreciate the nitty comments like this.

) -> PooledStreamChannel {
let reservation = self.lock.withLock {
self.state.reserveStream(
preferringPoolWithEventLoopID: preferredEventLoop.map { EventLoopID($0) }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we lift this preferredEventLoop.map call out of the lock? It's nice to do as little as possible while holding that lock.


switch reservation {
case let .success(poolIndex):
let channel = self.pools[poolIndex.value].makeStream(
Copy link
Collaborator

Choose a reason for hiding this comment

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

self.pools is var. Presumably we need to hold a lock here.

case .shutdownPools:
// Clear out the pools; we need to shut them down.
let pools = self.pools
self.pools.removeAll()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggest using keepingCapacity: true to avoid Array thinking we want to free memory.

Copy link
Collaborator

@Lukasa Lukasa left a comment

Choose a reason for hiding this comment

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

Cool, :shipit:

@glbrntt glbrntt merged commit a59aa82 into grpc:main Jun 1, 2021
@glbrntt glbrntt deleted the gb-pool-manager branch June 1, 2021 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔨 semver/patch No public API change.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants