Skip to content

Commit b8ed477

Browse files
quisquousCommit Bot
authored and
Commit Bot
committed
net: add optimization for SourceStream knowing it is complete
In http://crbug.com/957175, wanderview@ added an optimization for BlobReader where it would add an extra hop when finishing a stream. Many blobs size mojo::DataPipe to exactly fit the blob size, and so this can be quite common. As SourceStreamToDataPipe is going to be used in this CL (https://chromium-review.googlesource.com/c/chromium/src/+/1830360), that optimization needs to be carried forward. Bug: 1012869,957175 Change-Id: I9f7fc006b633a248fe3b726ac78d1fe4773472a6 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1862253 Reviewed-by: Eric Roman <eroman@chromium.org> Reviewed-by: Kinuko Yasuda <kinuko@chromium.org> Reviewed-by: Zentaro Kavanagh <zentaro@chromium.org> Commit-Queue: enne <enne@chromium.org> Cr-Commit-Position: refs/heads/master@{#707920}
1 parent b07c847 commit b8ed477

15 files changed

+86
-18
lines changed

chromeos/printing/ppd_line_reader.cc

+8-5
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,21 @@ class StringSourceStream : public net::SourceStream {
4747
int Read(net::IOBuffer* dest_buffer,
4848
int buffer_size,
4949
net::CompletionOnceCallback) override {
50-
int read_size = src_.size() - read_ofs_;
51-
if (read_size > buffer_size) {
52-
read_size = buffer_size;
53-
}
50+
if (buffer_size < 0)
51+
return net::ERR_INVALID_ARGUMENT;
52+
if (!MayHaveMoreBytes())
53+
return net::OK;
54+
const size_t read_size =
55+
std::min(src_.size() - read_ofs_, static_cast<size_t>(buffer_size));
5456
memcpy(dest_buffer->data(), src_.data() + read_ofs_, read_size);
5557
read_ofs_ += read_size;
5658
return read_size;
5759
}
5860
std::string Description() const override { return ""; }
61+
bool MayHaveMoreBytes() const override { return read_ofs_ < src_.size(); }
5962

6063
private:
61-
int read_ofs_ = 0;
64+
size_t read_ofs_ = 0;
6265
const std::string& src_;
6366
};
6467

net/filter/filter_source_stream.cc

+4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ std::string FilterSourceStream::Description() const {
7373
return next_type_string + "," + GetTypeAsString();
7474
}
7575

76+
bool FilterSourceStream::MayHaveMoreBytes() const {
77+
return !upstream_end_reached_;
78+
}
79+
7680
FilterSourceStream::SourceType FilterSourceStream::ParseEncodingType(
7781
const std::string& encoding) {
7882
if (encoding.empty()) {

net/filter/filter_source_stream.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ class NET_EXPORT_PRIVATE FilterSourceStream : public SourceStream {
3232

3333
~FilterSourceStream() override;
3434

35+
// SourceStream implementation.
3536
int Read(IOBuffer* read_buffer,
3637
int read_buffer_size,
3738
CompletionOnceCallback callback) override;
38-
3939
std::string Description() const override;
40+
bool MayHaveMoreBytes() const override;
4041

4142
static SourceType ParseEncodingType(const std::string& encoding);
4243

net/filter/fuzzed_source_stream.cc

+4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ std::string FuzzedSourceStream::Description() const {
7373
return "";
7474
}
7575

76+
bool FuzzedSourceStream::MayHaveMoreBytes() const {
77+
return !end_returned_;
78+
}
79+
7680
void FuzzedSourceStream::OnReadComplete(CompletionOnceCallback callback,
7781
const std::string& fuzzed_data,
7882
scoped_refptr<IOBuffer> read_buf,

net/filter/fuzzed_source_stream.h

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class FuzzedSourceStream : public SourceStream {
3232
int buffer_size,
3333
CompletionOnceCallback callback) override;
3434
std::string Description() const override;
35+
bool MayHaveMoreBytes() const override;
3536

3637
private:
3738
void OnReadComplete(CompletionOnceCallback callback,

net/filter/mock_source_stream.cc

+7-6
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,7 @@
1212

1313
namespace net {
1414

15-
MockSourceStream::MockSourceStream()
16-
: SourceStream(SourceStream::TYPE_NONE),
17-
read_one_byte_at_a_time_(false),
18-
awaiting_completion_(false),
19-
dest_buffer_(nullptr),
20-
dest_buffer_size_(0) {}
15+
MockSourceStream::MockSourceStream() : SourceStream(SourceStream::TYPE_NONE) {}
2116

2217
MockSourceStream::~MockSourceStream() {
2318
DCHECK(!awaiting_completion_);
@@ -53,6 +48,12 @@ std::string MockSourceStream::Description() const {
5348
return "";
5449
}
5550

51+
bool MockSourceStream::MayHaveMoreBytes() const {
52+
if (always_report_has_more_bytes_)
53+
return true;
54+
return !results_.empty();
55+
}
56+
5657
MockSourceStream::QueuedResult::QueuedResult(const char* data,
5758
int len,
5859
Error error,

net/filter/mock_source_stream.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class MockSourceStream : public SourceStream {
3535
int buffer_size,
3636
CompletionOnceCallback callback) override;
3737
std::string Description() const override;
38+
bool MayHaveMoreBytes() const override;
3839

3940
// Enqueues a result to be returned by |Read|. This method does not make a
4041
// copy of |data|, so |data| must outlive this object. If |mode| is SYNC,
@@ -55,6 +56,10 @@ class MockSourceStream : public SourceStream {
5556
read_one_byte_at_a_time_ = read_one_byte_at_a_time;
5657
}
5758

59+
void set_always_report_has_more_bytes(bool always_report_has_more_bytes) {
60+
always_report_has_more_bytes_ = always_report_has_more_bytes;
61+
}
62+
5863
// Returns true if a read is waiting to be completed.
5964
bool awaiting_completion() const { return awaiting_completion_; }
6065

@@ -68,12 +73,13 @@ class MockSourceStream : public SourceStream {
6873
const Mode mode;
6974
};
7075

71-
bool read_one_byte_at_a_time_;
76+
bool read_one_byte_at_a_time_ = false;
77+
bool always_report_has_more_bytes_ = true;
7278
base::queue<QueuedResult> results_;
73-
bool awaiting_completion_;
79+
bool awaiting_completion_ = false;
7480
scoped_refptr<IOBuffer> dest_buffer_;
7581
CompletionOnceCallback callback_;
76-
int dest_buffer_size_;
82+
int dest_buffer_size_ = 0;
7783

7884
DISALLOW_COPY_AND_ASSIGN(MockSourceStream);
7985
};

net/filter/source_stream.h

+6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ class NET_EXPORT_PRIVATE SourceStream {
5454
// logging.
5555
virtual std::string Description() const = 0;
5656

57+
// Returns true if there may be more bytes to read in this source stream.
58+
// This is not a guarantee that there are more bytes (in the case that
59+
// the stream doesn't know). However, if this returns false, then the stream
60+
// is guaranteed to be complete.
61+
virtual bool MayHaveMoreBytes() const = 0;
62+
5763
SourceType type() const { return type_; }
5864

5965
private:

net/tools/content_decoder_tool/content_decoder_tool.cc

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class StdinSourceStream : public SourceStream {
4949

5050
std::string Description() const override { return ""; }
5151

52+
bool MayHaveMoreBytes() const override { return true; }
53+
5254
private:
5355
std::istream* input_stream_;
5456

net/url_request/url_request_job.cc

+2
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ class URLRequestJob::URLRequestJobSourceStream : public SourceStream {
6767

6868
std::string Description() const override { return std::string(); }
6969

70+
bool MayHaveMoreBytes() const override { return true; }
71+
7072
private:
7173
// It is safe to keep a raw pointer because |job_| owns the last stream which
7274
// indirectly owns |this|. Therefore, |job_| will not be destroyed when |this|

services/network/public/cpp/data_pipe_to_source_stream.cc

+5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ std::string DataPipeToSourceStream::Description() const {
3131
return "DataPipe";
3232
}
3333

34+
bool DataPipeToSourceStream::MayHaveMoreBytes() const {
35+
return !complete_;
36+
}
37+
3438
int DataPipeToSourceStream::Read(net::IOBuffer* buf,
3539
int buf_size,
3640
net::CompletionOnceCallback callback) {
@@ -99,6 +103,7 @@ void DataPipeToSourceStream::OnReadable(MojoResult unused) {
99103
}
100104

101105
void DataPipeToSourceStream::FinishReading() {
106+
complete_ = true;
102107
handle_watcher_.Cancel();
103108
body_.reset();
104109
}

services/network/public/cpp/data_pipe_to_source_stream.h

+3
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ class COMPONENT_EXPORT(NETWORK_CPP) DataPipeToSourceStream final
1919
explicit DataPipeToSourceStream(mojo::ScopedDataPipeConsumerHandle body);
2020
~DataPipeToSourceStream() override;
2121

22+
// net::SourceStream implementation.
2223
int Read(net::IOBuffer* buf,
2324
int buf_size,
2425
net::CompletionOnceCallback callback) override;
2526
std::string Description() const override;
27+
bool MayHaveMoreBytes() const override;
2628

2729
private:
2830
void OnReadable(MojoResult result);
@@ -32,6 +34,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) DataPipeToSourceStream final
3234
mojo::SimpleWatcher handle_watcher_;
3335

3436
bool inside_read_ = false;
37+
bool complete_ = false;
3538

3639
scoped_refptr<net::IOBuffer> output_buf_;
3740
int output_buf_size_ = 0;

services/network/public/cpp/data_pipe_to_source_stream_unittest.cc

+8-2
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,19 @@ class DataPipeToSourceStreamTest
9696
WriteToPipe();
9797
rv = callback.WaitForResult();
9898
}
99-
if (rv == net::OK)
99+
if (rv == net::OK) {
100+
EXPECT_FALSE(adapter_->MayHaveMoreBytes());
100101
break;
101-
if (rv < net::OK)
102+
}
103+
if (rv < net::OK) {
104+
EXPECT_FALSE(adapter_->MayHaveMoreBytes());
102105
return rv;
106+
}
103107
EXPECT_GT(rv, net::OK);
104108
output->append(output_buffer_->data(), rv);
109+
EXPECT_TRUE(adapter_->MayHaveMoreBytes());
105110
}
111+
EXPECT_FALSE(adapter_->MayHaveMoreBytes());
106112
return 0;
107113
}
108114

services/network/public/cpp/source_stream_to_data_pipe.cc

+9-1
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,18 @@ void SourceStreamToDataPipe::DidRead(int result) {
7070
OnComplete(result);
7171
return;
7272
}
73+
7374
dest_ = pending_write_->Complete(result);
74-
pending_write_ = nullptr;
7575
transferred_bytes_ += result;
7676

77+
// Don't hop through an extra ReadMore just to find out there's no more data.
78+
if (!source_->MayHaveMoreBytes()) {
79+
OnComplete(net::OK);
80+
return;
81+
}
82+
83+
pending_write_ = nullptr;
84+
7785
base::SequencedTaskRunnerHandle::Get()->PostTask(
7886
FROM_HERE, base::BindOnce(&SourceStreamToDataPipe::ReadMore,
7987
weak_factory_.GetWeakPtr()));

services/network/public/cpp/source_stream_to_data_pipe_unittest.cc

+16
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,20 @@ TEST_P(SourceStreamToDataPipeTest, ConsumerClosed) {
196196
EXPECT_EQ(*CallbackResult(), net::ERR_ABORTED);
197197
}
198198

199+
TEST_P(SourceStreamToDataPipeTest, MayHaveMoreBytes) {
200+
const char message[] = "Hello, world!";
201+
202+
// Test that having the SourceStream properly report when !MayHaveMoreBytes
203+
// shortcuts extra work and still reports things properly.
204+
Init();
205+
source()->set_always_report_has_more_bytes(false);
206+
// Unlike other test reads (see "Simple" test), there is only one result here.
207+
source()->AddReadResult(message, sizeof(message) - 1, net::OK,
208+
GetParam().mode);
209+
adapter()->Start(callback());
210+
211+
std::string output;
212+
EXPECT_EQ(ReadPipe(&output), net::OK);
213+
EXPECT_EQ(output, message);
214+
}
199215
} // namespace network

0 commit comments

Comments
 (0)