Skip to content

Fix event counters 3. #3485

Merged
roji merged 5 commits intonpgsql:mainfrom
neyromant:fix_event_counters_3
Jan 28, 2021
Merged

Fix event counters 3. #3485
roji merged 5 commits intonpgsql:mainfrom
neyromant:fix_event_counters_3

Conversation

@neyromant
Copy link
Contributor

Another way to fix #3480, alternative for #3481

Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

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

LGTM - it's a very simple change and the locking should be meaningless perf-wise in these cold paths.

Any comments @vonzshik?

};

_poolsCounter = new PollingCounter("connection-pools", this, () => _pools)
_poolsCounter = new PollingCounter("connection-pools", this, () => _pools.Count)
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't this need to lock too?

Copy link
Contributor Author

@neyromant neyromant Jan 28, 2021

Choose a reason for hiding this comment

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

In the current implementation of HashSet, the Count property simply returns the value of the internal field m_count.
But maybe this could be changed in future versions. So I added lock just now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Or we can just add a count variable to avoid locking completely. But do not think it's that important.

Copy link
Contributor

Choose a reason for hiding this comment

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

Guys, it's just an atomic memory read even on 32-bit machine.

Copy link
Member

Choose a reason for hiding this comment

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

@YohDeadfall as @neyromant wrote, HashSet doesn't guarantee that this property is thread-safe - so why not be safe and lock? Are you (or @vonzshik) seeing any perf issue here that justifies taking risks, given that this lambda can get called only once per second at most?

Copy link
Contributor

Choose a reason for hiding this comment

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

Knowing the area and Microsoft well, I surely can say changes are very unexpected here. It might happen only if someone makes a faster less memory consuming hash set, but it's how the hash set works now in all frameworks.

Feel free to ignore my opinion here, but I still think that it's useless here.

Copy link
Contributor

@vonzshik vonzshik Jan 28, 2021

Choose a reason for hiding this comment

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

@YohDeadfall as @neyromant wrote, HashSet doesn't guarantee that this property is thread-safe - so why not be safe and lock? Are you (or @vonzshik) seeing any perf issue here that justifies taking risks, given that this lambda can get called only once per second at most?

I do not see any perf issues here. But if we can make it faster, while also not depending on HashSet.Count implementation, I do not see a reason why to not do so, especially when it doesn't cost us anything.

Copy link
Member

Choose a reason for hiding this comment

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

I agree with you that there's little chance this will change - but it's always better not to code assumptions like this which could break us later (as a matter of principle). Dictionary underwent some very serious changes in .NET Core, it could happen with HashSet too.

I don't want to ignore your opinion... But the more important answer I'm looking for, is what is the downside of using the lock (even if it is useless), given that this code is very cold. If you're seeing some scenario where this could impact us badly, I'd want to know about it... If there isn't one, then why not be safer?

Copy link
Contributor

Choose a reason for hiding this comment

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

The only difference between Dictionary<,> and HashSet<> is ability to store values. Otherwise, they are identical, both a hash sets with mostly the same set of methods. The chance is near to be zero since properties being methods under the hood should conform to execution cost requirement of O(1) and not perform any computations in case of getting a value.

There's a chance to face a multitenant application dealing with time limited passwords. In that case it might be critical, but otherwise, no downsides except that the lock takes much more time than the actual read.

Copy link
Member

Choose a reason for hiding this comment

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

There's a chance to face a multitenant application dealing with time limited passwords. In that case it might be critical, but otherwise, no downsides except that the lock takes much more time than the actual read.

Regardless of multitenant applications or time-limited passwords, the counter is polled once per second - that's as cold as can be. Any added overhead for the lock is going to be negligible.

@roji
Copy link
Member

roji commented Jan 28, 2021

Backported to 5.0.4 via 4fde949

roji pushed a commit that referenced this pull request Jan 28, 2021
Fixes #3480

Co-authored-by: Andrey.Kudashkin <andrey.kudashkin@russianpost.ru>
(cherry picked from commit c451b28)
neyromant pushed a commit to neyromant/npgsql that referenced this pull request Jan 31, 2021
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.

Busy/idle connection event counters are incorrect around multiple versions of the same connection string

4 participants