Skip to content

Commit

Permalink
rpc: linear time batch response matching (ethereum#23856)
Browse files Browse the repository at this point in the history
This avoids quadratic time complexity in the lookup of the batch element
corresponding to an RPC response. Unfortunately, the new approach
requires additional memory for the mapping from ID to index.

Fixes ethereum#22805
  • Loading branch information
fjl authored and zzyalbert committed Nov 26, 2021
1 parent dae3185 commit d98a0b7
Showing 1 changed file with 6 additions and 9 deletions.
15 changes: 6 additions & 9 deletions rpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package rpc

import (
"bytes"
"context"
"encoding/json"
"errors"
Expand Down Expand Up @@ -360,7 +359,10 @@ func (c *Client) BatchCall(b []BatchElem) error {
//
// Note that batch calls may not be executed atomically on the server side.
func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
msgs := make([]*jsonrpcMessage, len(b))
var (
msgs = make([]*jsonrpcMessage, len(b))
byID = make(map[string]int, len(b))
)
op := &requestOp{
ids: make([]json.RawMessage, len(b)),
resp: make(chan *jsonrpcMessage, len(b)),
Expand All @@ -372,6 +374,7 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
}
msgs[i] = msg
op.ids[i] = msg.ID
byID[string(msg.ID)] = i
}

var err error
Expand All @@ -391,13 +394,7 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
// Find the element corresponding to this response.
// The element is guaranteed to be present because dispatch
// only sends valid IDs to our channel.
var elem *BatchElem
for i := range msgs {
if bytes.Equal(msgs[i].ID, resp.ID) {
elem = &b[i]
break
}
}
elem := &b[byID[string(resp.ID)]]
if resp.Error != nil {
elem.Error = resp.Error
continue
Expand Down

0 comments on commit d98a0b7

Please sign in to comment.