Skip to content

Conversation

@ajaspers
Copy link
Contributor

@ajaspers ajaspers commented May 7, 2020

Opers can still see +i users.

Fixes #990.

@DanielOaks
Copy link
Member

DanielOaks commented May 7, 2020

Nice, awesome work mate. I wonder whether other servers do the thing of "if you're in a channel with an invisible user then you can see them in WHO * regardless". It sounds like something they may do, we should confirm how they act with regards to that and match them.

@ajaspers
Copy link
Contributor Author

ajaspers commented May 7, 2020

Indeed, I tried this on the InspIRCd testnet and WHO * returned a +i user with a shared channel.

@DanielOaks
Copy link
Member

DanielOaks commented May 7, 2020

Whoo, thanks for the test! We should probably reuse some of the 'friend' stuff we have, maybe add a new function called IsFriend(client) around here. (we use 'friend' to refer to 'user that's in a channel with us')

Otherwise we could merge this in and do that in a separate PR :D

@slingamn
Copy link
Member

slingamn commented May 7, 2020

I actually have no idea if this makes a meaningful difference to performance, but I'll mention it anyway since I was thinking about it: this technique does O(mn) lock acquisitions and releases, where m is the number of channels and n is the number of users.

I think what I'd want to do instead is:

  1. Make a hashset of the user's own channels
  2. For each potential friend who turns up in the WHO results, query their channels
  3. Iterate over the slice of returned channels and look for an intersecting element, using the hashset (this step no longer requires lock acquisitions)

Anyway if you don't want to do that, it's cool, this change is correct and I'm guessing the cost savings is not significant.

@ajaspers
Copy link
Contributor Author

ajaspers commented May 7, 2020

Ah, I see. That method is still O(m*n) but it would only require O(n) lock acquisitions. Acquiring read locks shouldn't block any other clients so I'm not sure of the impact either.

Should I get rid of the IsFriend() method then? Otherwise we would need to construct the user's channel set repeatedly, which is almost certainly going to be slower than acquiring read locks.

Also, does Oragono restrict the number of channels that a user can join? m in this case is the number of channels that a user can be in, not the number of channels on the server.

@slingamn
Copy link
Member

slingamn commented May 7, 2020

The recommended default (i.e., the one we ship in the default config file) is 100 channels per client. And yeah, you'd have to get rid of IsFriend and replace it with something that operates on the cached hash set of channels.

Anyway, it's chill if you don't want to do it, it's a premature optimization. I still have not fixed the worst offender in this regard, Channel.Names():

https://github.com/oragono/oragono/blob/c426cc8bab0381e7fb13c63f7cff5b8554c7debe/irc/channel.go#L463

Construct a hash set of the user's channels and check that rather than
querying channel membership, to reduce the number of locks that need to be
acquired.
@slingamn slingamn added this to the v2.1 milestone May 8, 2020
@slingamn
Copy link
Member

slingamn commented May 8, 2020

Thanks for putting up with the bikeshedding <3

@slingamn slingamn merged commit d187cc5 into ergochat:master May 8, 2020
@ajaspers ajaspers deleted the who_invisible branch May 8, 2020 02:12
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.

invisible users are visible in who *

3 participants