-
Notifications
You must be signed in to change notification settings - Fork 267
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 router performance #2651
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention:
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## master #2651 +/- ##
==========================================
+ Coverage 85.85% 85.92% +0.07%
==========================================
Files 216 216
Lines 18201 18221 +20
Branches 749 789 +40
==========================================
+ Hits 15626 15656 +30
+ Misses 2575 2565 -10
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a useful change, but I dislike the volatile
wrapper. We should also probably motivate this change with benchmarks, like any non-trivial change made solely for performance gains.
@@ -71,7 +71,7 @@ class Router(val nodeParams: NodeParams, watcher: typed.ActorRef[ZmqWatcher.Comm | |||
|
|||
val db: NetworkDb = nodeParams.db.network | |||
|
|||
{ | |||
private val dataHolder: VolatileRouterDataHolder = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is overkill and will very likely create hard-to-debug performance issues. We only need two things to be accessible from the worker actors:
- the
excludedChannels
: this should be a small list, it's probably fine to copy it - the
graphWithBalances
: this is a large data structure that we definitely don't want to copy, but we can probably make it thread-safe by simply using standard thread-safe collections? It would be useful to benchmark the cost of those changes
That’s a simple way to avoid Memory Consistency Errors in JVM. And it does the job, since all updates are made in one thread. IMHO the real overkill is that My goal was to make the least invasive change, so I introduced I’d prefer to drop class Router(val nodeParams: NodeParams, watcher: typed.ActorRef[ZmqWatcher.Command], initialized: Option[Promise[Done]] = None) extends Actor {
private val data = VolatileRouterData()
def receive =
…
case PeerRoutingMessage(peerConnection, remoteNodeId, c: ChannelAnnouncement) =>
data.update(
= Validation.handleChannelAnnouncement(data, watcher, RemoteGossip(peerConnection, remoteNodeId), c))
…
case r: RouteRequest =>
worker ! Worker.FindRoutes(data, r, sender())
…
}
} It’s not really Haskell style, but easy to understand, easy to maintain, and there’s absolutely no Java concurrent programming fun.
You can find some benchmarks here #2644 |
This PR parallelizes route calculations. It creates a bunch of worker actors that perform route calculation in parallel.
As a side effect it prevents the
Router
's mailbox from clogging with route requests, so it can process network updates on time.See #2644 for the context.