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

rfc: refactoring Server #640

Open
4e554c4c opened this issue Nov 6, 2024 · 7 comments · May be fixed by #724
Open

rfc: refactoring Server #640

4e554c4c opened this issue Nov 6, 2024 · 7 comments · May be fixed by #724

Comments

@4e554c4c
Copy link
Contributor

4e554c4c commented Nov 6, 2024

The Problem

When working on #77 I have run into numerous issues with how to represent a "server" in halloy. The Server struct, which is a wrapper around String, is currently ubiquitous in the halloy codebase, however it has many issues. Since Server is a String, &Server is &String, which is an anti-pattern. Variables of type &Server must be .clone()d often to satisfy lifetime issues and in order to satisfy lifetime constraints, which leads to the same "server name" being duplicated all over the codebase. For example, it must be cloned every time a message is received by the IRC server to communicate the server updated between the "stream" and "client".

In order to implement #77, the way that servers are referenced must be changed as well. In a bouncer-networks setup, several "primary" servers each set up any number of secondary servers. Thus there is a hierarchical relationship between servers, and a single config is shared between many. Furthermore, servers can no longer be identified by their name. Names may not be unique (two secondaries on under two different primaries may match), and are not the canonical way to refer to a server (the canonical identifier for a "secondary" server is its bouncer NETID).

Therefore, however we represent Server, it cannot also be used as the human-visible name for a server, which causes issues elsewhere in the codebase

A Proposed Solution

Ideally, in order to send a Server identifier with every single irc message, the Server type should be Copy (not just Clone!) and cheap to replicate. Furthermore, we should be able to get additional data that a Server represents by asking a centralized source of information.

My proposal is as follows: Server should be a Uuid (either v4 or v5). This data can be cheaply copied and sent between tasks without a performance overhead. Then, when it is necessary to look up server information (such as user-visible name) this can be gathered by looking at the a HashMap<Uuid, ServerInfo> which contains server config name, bouncer ID, bouncer name, etc.

CCs

@tarkah , @casperstorm let me know what you think. Last time I brought this up you mentioned that I should open an RFC before doing any huge refactors with Server and friends 😸

@tarkah
Copy link
Member

tarkah commented Nov 7, 2024

Sounds reasonable! I don't even think we need a UUID. Since the server name from the toml config has to be unique, we can simply hash it and use that as the u64 id.

@4e554c4c
Copy link
Contributor Author

4e554c4c commented Nov 7, 2024

Sounds reasonable! I don't even think we need a UUID. Since the server name from the toml config has to be unique, we can simply hash it and use that as the u64 id.

Yes, but the issue is that since bouncer-networks (#77) would mean multiple servers / connections for a single TOML "server name", we need a better way to identify servers

for example, two servers from two different bouncers could be called "libera"

@tarkah
Copy link
Member

tarkah commented Nov 7, 2024

Makes sense 👍

@4e554c4c
Copy link
Contributor Author

4e554c4c commented Nov 7, 2024

Ok i'll try to work on this separately from the bouncer-networks stuff (since that's already getting kind of complicated) and we'll see how it looks 🎉

@4e554c4c
Copy link
Contributor Author

4e554c4c commented Nov 9, 2024

I think I'm going to try to make it a v5 UUID with a consistent hash function, so that we can use these in the history in lieu of server names

@4e554c4c
Copy link
Contributor Author

I'm thinking that UUIDs might actually be a bad idea. But a better idea might be putting Server in an Arc so that it isn't unnecessarily copied

@4e554c4c
Copy link
Contributor Author

I tried making Server an Arc<str> and this was the result:

Before:

________________________________________________________
Executed in   28.64 secs    fish           external
   usr time    6.80 secs  828.00 micros    6.80 secs
   sys time    0.84 secs  193.00 micros    0.84 secs

After:

________________________________________________________
Executed in   32.78 secs    fish           external
   usr time    6.38 secs    0.00 millis    6.38 secs
   sys time    0.91 secs    1.53 millis    0.91 secs

So a 4% cpu usage reduction which is pretty nice

4e554c4c added a commit to 4e554c4c/halloy that referenced this issue Jan 23, 2025
This commit includes various fixes that I have found working on
bouncer-networks. It includes several performance benefits—such as
changing `Server` to be an `Arc<str>` which removes much of the copying
overhead. I have also made sure that there is only one copy of the
server config in the `Halloy` struct, which was previously duplicated
for seemingly no reason.
Still, several performance issues go un-addressed. such as the
duplication of server configs between threads (should this also be an
`Arc<config>`?) and the copying of `client` structs.

I have also made some changes to the client. The capability negotiation
process has been streamlined, and I've eliminated some branching with
preference toward pattern matching. I've also fixed a slight error with
halloy, making sure that it detects the end of registration correctly
(matching other clients).

I have also made changes to the `Cargo.toml` in the `data` crate. This
is to fix some compilation issues when building that crate in isolation.
I would like this fixed so that it'd be easier to run `data` crate tests
in isolation.
Ideally I think that each of the sub-crates should be tested
individually in CI—but that's out of scope for this PR.

In my opinion, this resolves squidowl#640
@4e554c4c 4e554c4c linked a pull request Jan 23, 2025 that will close this issue
4e554c4c added a commit to 4e554c4c/halloy that referenced this issue Jan 23, 2025
This commit includes various fixes that I have found working on
bouncer-networks. It includes several performance benefits—such as
changing `Server` to be an `Arc<str>` which removes much of the copying
overhead. I have also made sure that there is only one copy of the
server config in the `Halloy` struct, which was previously duplicated
for seemingly no reason.
Still, several performance issues go un-addressed. such as the
duplication of server configs between threads (should this also be an
`Arc<config>`?) and the copying of `client` structs.

I have also made some changes to the client. The capability negotiation
process has been streamlined, and I've eliminated some branching with
preference toward pattern matching. I've also fixed a slight error with
halloy, making sure that it detects the end of registration correctly
(matching other clients).

I have also made changes to the `Cargo.toml` in the `data` crate. This
is to fix some compilation issues when building that crate in isolation.
I would like this fixed so that it'd be easier to run `data` crate tests
in isolation.
Ideally I think that each of the sub-crates should be tested
individually in CI—but that's out of scope for this PR.

In my opinion, this resolves squidowl#640
4e554c4c added a commit to 4e554c4c/halloy that referenced this issue Jan 27, 2025
This commit includes various fixes that I have found working on
bouncer-networks. It includes several performance benefits—such as
changing `Server` to be an `Arc<str>` which removes much of the copying
overhead. I have also made sure that there is only one copy of the
server config in the `Halloy` struct, which was previously duplicated
for seemingly no reason.
Still, several performance issues go un-addressed. such as the
duplication of server configs between threads (should this also be an
`Arc<config>`?) and the copying of `client` structs.

I have also made some changes to the client. The capability negotiation
process has been streamlined, and I've eliminated some branching with
preference toward pattern matching. I've also fixed a slight error with
halloy, making sure that it detects the end of registration correctly
(matching other clients).

I have also made changes to the `Cargo.toml` in the `data` crate. This
is to fix some compilation issues when building that crate in isolation.
I would like this fixed so that it'd be easier to run `data` crate tests
in isolation.
Ideally I think that each of the sub-crates should be tested
individually in CI—but that's out of scope for this PR.

In my opinion, this resolves squidowl#640
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 a pull request may close this issue.

2 participants