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

Improve how ConnectionAcquisitionTimeout is checked #233

Merged
merged 7 commits into from
Sep 18, 2017

Conversation

ali-ince
Copy link
Contributor

No description provided.

…ol and converted recursive calls to loops in order to avoid any possible stack overflows.
Copy link
Contributor

@zhenlineo zhenlineo left a comment

Choose a reason for hiding this comment

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

Totally agree with the CancelationToken conn acquisition part, but I am a bit concerned to totally remove ConnAcquisitionQueuingTimeout.

return connection;
});
}
catch (OperationCanceledException ex)
Copy link
Contributor

Choose a reason for hiding this comment

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

I am thinking that this try-catch should be inside return TryExecute. TryExecute is only used to log errors before throwing the error to user. I would think this OperationCanceledException is less interesting to an end user than ClientException

break;
}

if (_availableConnections.TryTake(out connection, 0, cancellationToken))
Copy link
Contributor

Choose a reason for hiding this comment

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

Why removed ConnAcquisitionQueuingTimeout? We initially want this blocking queue is to make thread wait a bit on this TryTake method to introduce some queuing/waiting inside async. I am a bit worried if we return directly without any sleep, will the thread span here a lot?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've put a small time lapse back into the loop (not a magnitude of seconds but milliseconds) but remove those timeouts and cancellationtoken checking logic from the first TryTake - making the fast path do not bother with those.

Copy link
Contributor

@lutovich lutovich left a comment

Choose a reason for hiding this comment

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

@ali-ince looks good, two small comments

{
break;
;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this ; intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, indeed :)

{
if (!IsConnectionPoolFull())
{
connection = CreateNewPooledConnection();
Copy link
Contributor

Choose a reason for hiding this comment

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

Unrelated to this PR: given a pool with maxConnectionPoolSize - 1 acquired and 0 idle connections, can two threads that call Acquire() concurrently make pool expand to maxConnectionPoolSize + 1 active connections? They will both try to create concurrently and attempts are probably not synchronized.

Copy link
Contributor

Choose a reason for hiding this comment

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

Except for correctness, I am not fan to strictly not exceed maxConnPoolSize. As it not only slows the code down also bring more complete logic.

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggesting to have the fix in another PR. Right now the scope of this PR is good enough and the problem is not critical to block 1.5.

@ali-ince
Copy link
Contributor Author

I think I've addressed the synchronization issue you've pointed out.

Copy link
Contributor

@lutovich lutovich left a comment

Choose a reason for hiding this comment

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

@ali-ince two more comments about synchronization around maxPoolSize

{
if (_poolSize > _maxPoolSize)
{
throw new InvalidOperationException();
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we also decrement _poolSize here?

@@ -151,6 +149,17 @@ public IPooledConnection CreateNewPooledConnection()
private PooledConnection NewPooledConnection()
{
Interlocked.Increment(ref _poolSize);
if (_maxPoolSize != Config.Infinite && _poolSize > _maxPoolSize)
Copy link
Contributor

Choose a reason for hiding this comment

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

If we have two threads and _poolSize == _maxPoolSize - 1 they both will increment _poolSize and throw, right? I think one of them should succeed. We could probably use result of Interlocked.Increment to figure out which one should fail.

@ali-ince ali-ince merged commit 507a6fa into neo4j:1.5 Sep 18, 2017
@ali-ince ali-ince deleted the 1.5-improve-acquisition-timeout branch September 27, 2017 08:50
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.

3 participants