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

Expand stream's flow control in case of an active read. #1248

Merged
merged 13 commits into from May 23, 2017

Conversation

MakMukhi
Copy link
Contributor

@MakMukhi MakMukhi commented May 18, 2017

Building on original PR by apolcyn@ #1073

Benchmark on scenario:

{  
   "scenarios":[  
      {  
         "name":"go_protobuf_sync_unary_ping_pong_secure_2097152db",
         "warmup_seconds":5,
         "benchmark_seconds":30,
         "num_servers":1,
         "server_config":{  
            "async_server_threads":0,
            "security_params":{  
               "use_test_ca":true,
               "server_host_override":"foo.test.google.fr"
            },
            "payload_config":{  
               "simple_params":{  
                  "resp_size":2097152,
                  "req_size":2097152
               }
            },
            "server_type":"SYNC_SERVER"
         },
         "client_config":{  
            "client_type":"SYNC_CLIENT",
            "security_params":{  
               "use_test_ca":true,
               "server_host_override":"foo.test.google.fr"
            },
            "payload_config":{  
               "simple_params":{  
                  "resp_size":2097152,
                  "req_size":2097152
               }
            },
            "client_channels":1,
            "async_client_threads":1,
            "outstanding_rpcs_per_channel":1,
            "rpc_type":"UNARY",
            "load_params":{  
               "closed_loop":{  

               }
            },
            "histogram_params":{  
               "max_possible":60000000000.0,
               "resolution":0.01
            }
         },
         "num_clients":1
      }
   ]
}

Results before the changes: QPS: 0.1

Results after the changes: QPS: 0.9

}
f.mu.Lock()
defer f.mu.Unlock()
senderQuota := int32(f.limit - (f.pendingData + f.pendingUpdate))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small wording nit: rename to estimatedSenderQuota and estimatedUntransmittedData, for clarity here?

@@ -167,14 +169,37 @@ type inFlow struct {
// The amount of data the application has consumed but grpc has not sent
// window update for them. Used to reduce window update frequency.
pendingUpdate uint32
// delta is the extra window update given by receiver when an application
// is reading data bigger in size than the inFlow limit.
delta int32
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be unsigned since it can't be negative? (Also, you cast it to uint32 when reading and cast to int32 when assigning.)

@@ -189,6 +214,14 @@ func (f *inFlow) onRead(n uint32) uint32 {
return 0
}
f.pendingData -= n
if f.delta > 0 {
f.delta -= int32(n)
Copy link
Member

@dfawley dfawley May 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be easier to read without the casts and taking the negative of a negative number:

if n > f.delta {
  n -= f.delta
  f.delta = 0
} else {
  f.delta -= n
  n = 0
}

(Also would allow f.delta to be uint32 like it seems like it wants to be.)

@@ -173,9 +173,9 @@ func newHTTP2Client(ctx context.Context, addr TargetInfo, opts ConnectOptions) (
conn, err := dial(ctx, opts.Dialer, addr.Addr)
if err != nil {
if opts.FailOnNonTempDialError {
return nil, connectionErrorf(isTemporary(err), err, "transport: %v", err)
return nil, connectionErrorf(isTemporary(err), err, "transport: Error while dialing %v", err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: lowercase "e" in "error", and add a colon before the error being appended.

if s.state == streamDone {
return
}
if w := s.fc.maybeAdjust(n); n > 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the if be checking w?

If not, check n first.

if s.state == streamDone {
return
}
if w := s.fc.maybeAdjust(n); n > 0 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above re: w and n.

Can this function be shared somehow? Should it be a method on the Stream instead of server/client?

// Read reads all the data available for this Stream from the transport and
// Read reads all p bytes from the wire for this stream.
func (s *Stream) Read(p []byte) (n int, err error) {
// Don't request a read if there's was an error earlier
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: "there was"

te := newTest(t, e)
te.startServer(&testServer{security: e.security})
defer te.tearDown()
tc := testpb.NewTestServiceClient(te.clientConn())

stream, err := tc.StreamingInputCall(te.ctx)
ctx, _ := context.WithTimeout(te.ctx, time.Minute*3)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: 30s

@@ -67,7 +75,7 @@ func TestSimpleParsing(t *testing.T) {
// Check that messages with length >= 2^24 are parsed.
{append([]byte{0, 1, 0, 0, 0}, bigMsg...), nil, bigMsg, compressionNone},
} {
buf := bytes.NewReader(test.p)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think the use of fullReader and other changes to this file can be reverted, since the transport is still an io.Reader.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These test here rely on recvMsg's behavior of reading the full message, (which is true when it interacts with the transport stream). However, here the parser is given a "fake" buffer instead of the stream. Given that we changed recvMsg to go from io.ReadFull to p.r.Read, the "fake" buffer here needs to read the full message just like the transport stream does.

}
f.mu.Lock()
defer f.mu.Unlock()
estSenderQuota := int32(f.limit - (f.pendingData + f.pendingUpdate))
Copy link
Contributor

@apolcyn apolcyn May 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional nit, sorry one more naming suggestion:
change to maxPossibleSenderQuota and minPossibleUnTransmittedData (keep estUnTransmitted)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about I add comments and leave the names as is? I fear long names take us away from Go-styling.

inBuf := make([]byte, 1)
actualCount, actualErr := s.Read(inBuf)
if actualCount != 0 {
t.Errorf("actualCount, _ := s.Read(_) differs; want %v; got %v", 0, actualCount)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: s/want %v/want 0

menghanl added a commit to menghanl/grpc-go that referenced this pull request May 24, 2017
@menghanl menghanl added 1.4 Type: Performance Performance improvements (CPU, network, memory, etc) labels Jun 7, 2017
@MakMukhi MakMukhi deleted the stream_window branch May 4, 2018 02:10
@lock lock bot locked as resolved and limited conversation to collaborators Oct 31, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Type: Performance Performance improvements (CPU, network, memory, etc)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants