rpc: linear time batch response matching (#23856)
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 #22805
This commit is contained in:
parent
03bc8b7858
commit
53b94f135a
@ -17,7 +17,6 @@
|
|||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
@ -360,7 +359,10 @@ func (c *Client) BatchCall(b []BatchElem) error {
|
|||||||
//
|
//
|
||||||
// Note that batch calls may not be executed atomically on the server side.
|
// Note that batch calls may not be executed atomically on the server side.
|
||||||
func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
|
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{
|
op := &requestOp{
|
||||||
ids: make([]json.RawMessage, len(b)),
|
ids: make([]json.RawMessage, len(b)),
|
||||||
resp: make(chan *jsonrpcMessage, len(b)),
|
resp: make(chan *jsonrpcMessage, len(b)),
|
||||||
@ -372,6 +374,7 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
|
|||||||
}
|
}
|
||||||
msgs[i] = msg
|
msgs[i] = msg
|
||||||
op.ids[i] = msg.ID
|
op.ids[i] = msg.ID
|
||||||
|
byID[string(msg.ID)] = i
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -391,13 +394,7 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
|
|||||||
// Find the element corresponding to this response.
|
// Find the element corresponding to this response.
|
||||||
// The element is guaranteed to be present because dispatch
|
// The element is guaranteed to be present because dispatch
|
||||||
// only sends valid IDs to our channel.
|
// only sends valid IDs to our channel.
|
||||||
var elem *BatchElem
|
elem := &b[byID[string(resp.ID)]]
|
||||||
for i := range msgs {
|
|
||||||
if bytes.Equal(msgs[i].ID, resp.ID) {
|
|
||||||
elem = &b[i]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if resp.Error != nil {
|
if resp.Error != nil {
|
||||||
elem.Error = resp.Error
|
elem.Error = resp.Error
|
||||||
continue
|
continue
|
||||||
|
Loading…
Reference in New Issue
Block a user