Here's what I see that can be optimized.
Distance checks
For each player (i.e., recipient), when determing which other players the recipient can see (i.e., senders), instead of looping all players, loop only the players in the network groups the recipient is subscribed to (including the global network group). Doing this should allow you to perform fewer distance checks. Note: This is a fairly minor optimization since the distance checks are the least expensive of the methods being used in this plugin.
Raycasts
- If a player was visible for the previous raycast, stop raycasting from the recipient player to that sender player for a few seconds. The consequence of this is that when either player goes behind an object, the recipient would still receive updates from the sender for a few moments, but that's not a big deal and saves lots of raycasts for players who are continuously visible to each other. Note: This is a fairly minor optimization since it does not improve the case where they players are constantly not visible to each other, which is probably the majority case.
- Implement a system of risk levels to completely exempt most players. For example, implement a standalone plugin whose sole purpose is to assign players risk levels that other plugins can consume. That plugin can derive player risk levels from a variety of sources, including EAC events, anti-cheat plugin events (e.g., Arkan, stash traps), 3rd party information (e.g., steam account age, hours in game), hours on server, affiliation with other high risk players, and possibly other 3rd party community databases. If a player (recipient) has a sufficiently low risk level, this plugin will not perform any network-limiting logic for them, so they will be networked all players in their network groups.
Component lookup
Don't call GetComponent in CanNetworkTo, since GetComponent is relatively slow. Instead, use dictionaries for faster lookup.
CanNetworkTo
Instead of using CanNetworkTo, implement a custom network group provider. This will be mostly copy-pasta of the vanilla positional network group provider, but you can use alternate logic for players. Basically, each recipient player who has limited network visibility (i.e., the high risk players), will have a separate network group dedicated for sender players that recipient can see. Players should be disallowed from the standard positional network groups and instead only placed in network groups of the recipients who should be able to see them. When you want to toggle visibility for a sender player, toggle their presence in the recipient's network group. This approach can save a lot of overhead, but don't expect it to be simple or straight-forward to implement.