Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: net/quic/core/quic_stream_sequencer_buffer_test.cc

Issue 2328633004: lazy allocation and early release memory in QuicStreamSequencerBuffer. Protected by --quic_reduce_s… (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/core/quic_stream_sequencer_buffer.cc ('k') | net/quic/core/reliable_quic_stream.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 #include "net/quic/core/quic_stream_sequencer_buffer.h" 4 #include "net/quic/core/quic_stream_sequencer_buffer.h"
5 5
6 #include <algorithm> 6 #include <algorithm>
7 #include <limits> 7 #include <limits>
8 #include <map> 8 #include <map>
9 #include <string> 9 #include <string>
10 #include <utility> 10 #include <utility>
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 QuicStreamSequencerBuffer::kBlockSizeBytes; 53 QuicStreamSequencerBuffer::kBlockSizeBytes;
54 typedef QuicStreamSequencerBuffer::BufferBlock BufferBlock; 54 typedef QuicStreamSequencerBuffer::BufferBlock BufferBlock;
55 typedef QuicStreamSequencerBuffer::Gap Gap; 55 typedef QuicStreamSequencerBuffer::Gap Gap;
56 typedef QuicStreamSequencerBuffer::FrameInfo FrameInfo; 56 typedef QuicStreamSequencerBuffer::FrameInfo FrameInfo;
57 57
58 class QuicStreamSequencerBufferPeer { 58 class QuicStreamSequencerBufferPeer {
59 public: 59 public:
60 explicit QuicStreamSequencerBufferPeer(QuicStreamSequencerBuffer* buffer) 60 explicit QuicStreamSequencerBufferPeer(QuicStreamSequencerBuffer* buffer)
61 : buffer_(buffer) {} 61 : buffer_(buffer) {}
62 62
63 // Read from this buffer_->into the given destination buffer_-> up to the 63 // Read from this buffer_ into the given destination buffer_ up to the
64 // size of the destination. Returns the number of bytes read. Reading from 64 // size of the destination. Returns the number of bytes read. Reading from
65 // an empty buffer_->returns 0. 65 // an empty buffer_->returns 0.
66 size_t Read(char* dest_buffer, size_t size) { 66 size_t Read(char* dest_buffer, size_t size) {
67 iovec dest; 67 iovec dest;
68 dest.iov_base = dest_buffer, dest.iov_len = size; 68 dest.iov_base = dest_buffer, dest.iov_len = size;
69 return buffer_->Readv(&dest, 1); 69 return buffer_->Readv(&dest, 1);
70 } 70 }
71 71
72 // If buffer is empty, the blocks_ array must be empty, which means all 72 // If buffer is empty, the blocks_ array must be empty, which means all
73 // blocks are deallocated. 73 // blocks are deallocated.
74 bool CheckEmptyInvariants() { 74 bool CheckEmptyInvariants() {
75 return !buffer_->Empty() || IsBlockArrayEmpty(); 75 return !buffer_->Empty() || IsBlockArrayEmpty();
76 } 76 }
77 77
78 bool IsBlockArrayEmpty() { 78 bool IsBlockArrayEmpty() {
79 if (FLAGS_quic_reduce_sequencer_buffer_memory_life_time && // NOLINT
80 buffer_->blocks_ == nullptr) {
81 return true;
82 }
83
79 size_t count = buffer_->blocks_count_; 84 size_t count = buffer_->blocks_count_;
80 for (size_t i = 0; i < count; i++) { 85 for (size_t i = 0; i < count; i++) {
81 if (buffer_->blocks_[i] != nullptr) { 86 if (buffer_->blocks_[i] != nullptr) {
82 return false; 87 return false;
83 } 88 }
84 } 89 }
85 return true; 90 return true;
86 } 91 }
87 92
88 bool CheckInitialState() { 93 bool CheckInitialState() {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 std::map<QuicStreamOffset, FrameInfo>* frame_arrival_time_map() { 148 std::map<QuicStreamOffset, FrameInfo>* frame_arrival_time_map() {
144 return &(buffer_->frame_arrival_time_map_); 149 return &(buffer_->frame_arrival_time_map_);
145 } 150 }
146 151
147 void set_total_bytes_read(QuicStreamOffset total_bytes_read) { 152 void set_total_bytes_read(QuicStreamOffset total_bytes_read) {
148 buffer_->total_bytes_read_ = total_bytes_read; 153 buffer_->total_bytes_read_ = total_bytes_read;
149 } 154 }
150 155
151 void set_gaps(const std::list<Gap>& gaps) { buffer_->gaps_ = gaps; } 156 void set_gaps(const std::list<Gap>& gaps) { buffer_->gaps_ = gaps; }
152 157
158 bool IsBufferAllocated() { return buffer_->blocks_ != nullptr; }
159
153 private: 160 private:
154 QuicStreamSequencerBuffer* buffer_; 161 QuicStreamSequencerBuffer* buffer_;
155 }; 162 };
156 163
157 namespace { 164 namespace {
158 165
159 class QuicStreamSequencerBufferTest : public testing::Test { 166 class QuicStreamSequencerBufferTest : public testing::Test {
160 public: 167 public:
161 void SetUp() override { Initialize(); } 168 void SetUp() override { Initialize(); }
162 169
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 208
202 TEST_F(QuicStreamSequencerBufferTest, OnStreamData0length) { 209 TEST_F(QuicStreamSequencerBufferTest, OnStreamData0length) {
203 size_t written; 210 size_t written;
204 QuicErrorCode error = buffer_->OnStreamData(800, "", clock_.ApproximateNow(), 211 QuicErrorCode error = buffer_->OnStreamData(800, "", clock_.ApproximateNow(),
205 &written, &error_details_); 212 &written, &error_details_);
206 EXPECT_EQ(error, QUIC_EMPTY_STREAM_FRAME_NO_FIN); 213 EXPECT_EQ(error, QUIC_EMPTY_STREAM_FRAME_NO_FIN);
207 EXPECT_TRUE(helper_->CheckBufferInvariants()); 214 EXPECT_TRUE(helper_->CheckBufferInvariants());
208 } 215 }
209 216
210 TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) { 217 TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) {
218 if (FLAGS_quic_reduce_sequencer_buffer_memory_life_time) { // NOLINT
219 EXPECT_FALSE(helper_->IsBufferAllocated());
220 }
211 string source(1024, 'a'); 221 string source(1024, 'a');
212 size_t written; 222 size_t written;
213 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); 223 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
214 QuicTime t = clock_.ApproximateNow(); 224 QuicTime t = clock_.ApproximateNow();
215 EXPECT_EQ(QUIC_NO_ERROR, 225 EXPECT_EQ(QUIC_NO_ERROR,
216 buffer_->OnStreamData(800, source, t, &written, &error_details_)); 226 buffer_->OnStreamData(800, source, t, &written, &error_details_));
217 BufferBlock* block_ptr = helper_->GetBlock(0); 227 BufferBlock* block_ptr = helper_->GetBlock(0);
218 for (size_t i = 0; i < source.size(); ++i) { 228 for (size_t i = 0; i < source.size(); ++i) {
219 ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]); 229 ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]);
220 } 230 }
221 EXPECT_EQ(2, helper_->GapSize()); 231 EXPECT_EQ(2, helper_->GapSize());
222 std::list<Gap> gaps = helper_->GetGaps(); 232 std::list<Gap> gaps = helper_->GetGaps();
223 EXPECT_EQ(800u, gaps.front().end_offset); 233 EXPECT_EQ(800u, gaps.front().end_offset);
224 EXPECT_EQ(1824u, gaps.back().begin_offset); 234 EXPECT_EQ(1824u, gaps.back().begin_offset);
225 auto* frame_map = helper_->frame_arrival_time_map(); 235 auto* frame_map = helper_->frame_arrival_time_map();
226 EXPECT_EQ(1u, frame_map->size()); 236 EXPECT_EQ(1u, frame_map->size());
227 EXPECT_EQ(800u, frame_map->begin()->first); 237 EXPECT_EQ(800u, frame_map->begin()->first);
228 EXPECT_EQ(t, (*frame_map)[800].timestamp); 238 EXPECT_EQ(t, (*frame_map)[800].timestamp);
229 EXPECT_TRUE(helper_->CheckBufferInvariants()); 239 EXPECT_TRUE(helper_->CheckBufferInvariants());
240 EXPECT_TRUE(helper_->IsBufferAllocated());
230 } 241 }
231 242
232 TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithOverlap) { 243 TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithOverlap) {
233 string source(1024, 'a'); 244 string source(1024, 'a');
234 // Write something into [800, 1824) 245 // Write something into [800, 1824)
235 size_t written; 246 size_t written;
236 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); 247 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
237 QuicTime t1 = clock_.ApproximateNow(); 248 QuicTime t1 = clock_.ApproximateNow();
238 EXPECT_EQ(QUIC_NO_ERROR, 249 EXPECT_EQ(QUIC_NO_ERROR,
239 buffer_->OnStreamData(800, source, t1, &written, &error_details_)); 250 buffer_->OnStreamData(800, source, t1, &written, &error_details_));
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 } 545 }
535 546
536 TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsEmpty) { 547 TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsEmpty) {
537 iovec iovs[2]; 548 iovec iovs[2];
538 int iov_count = buffer_->GetReadableRegions(iovs, 2); 549 int iov_count = buffer_->GetReadableRegions(iovs, 2);
539 EXPECT_EQ(0, iov_count); 550 EXPECT_EQ(0, iov_count);
540 EXPECT_EQ(nullptr, iovs[iov_count].iov_base); 551 EXPECT_EQ(nullptr, iovs[iov_count].iov_base);
541 EXPECT_EQ(0u, iovs[iov_count].iov_len); 552 EXPECT_EQ(0u, iovs[iov_count].iov_len);
542 } 553 }
543 554
555 TEST_F(QuicStreamSequencerBufferTest, ReleaseWholeBuffer) {
556 // Tests that buffer is not deallocated unless ReleaseWholeBuffer() is called.
557 if (!FLAGS_quic_reduce_sequencer_buffer_memory_life_time) { // NOLINT
558 // Won't release buffer when flag is off.
559 return;
560 }
561
562 string source(100, 'b');
563 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
564 QuicTime t1 = clock_.ApproximateNow();
565 // Write something into [0, 100).
566 size_t written;
567 buffer_->OnStreamData(0, source, t1, &written, &error_details_);
568 EXPECT_TRUE(buffer_->HasBytesToRead());
569 char dest[120];
570 iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}};
571 size_t read = buffer_->Readv(iovecs, 3);
572 EXPECT_EQ(100u, read);
573 EXPECT_EQ(100u, buffer_->BytesConsumed());
574 EXPECT_TRUE(helper_->CheckBufferInvariants());
575 EXPECT_TRUE(helper_->IsBufferAllocated());
576 buffer_->ReleaseWholeBuffer();
577 EXPECT_FALSE(helper_->IsBufferAllocated());
578 }
579
544 TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsBlockedByGap) { 580 TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsBlockedByGap) {
545 // Write into [1, 1024). 581 // Write into [1, 1024).
546 string source(1023, 'a'); 582 string source(1023, 'a');
547 size_t written; 583 size_t written;
548 buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written, 584 buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written,
549 &error_details_); 585 &error_details_);
550 // Try to get readable regions, but none is there. 586 // Try to get readable regions, but none is there.
551 iovec iovs[2]; 587 iovec iovs[2];
552 int iov_count = buffer_->GetReadableRegions(iovs, 2); 588 int iov_count = buffer_->GetReadableRegions(iovs, 2);
553 EXPECT_EQ(0, iov_count); 589 EXPECT_EQ(0, iov_count);
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
1078 EXPECT_LE(bytes_to_buffer_, total_bytes_read_) << "iterations: " 1114 EXPECT_LE(bytes_to_buffer_, total_bytes_read_) << "iterations: "
1079 << iterations; 1115 << iterations;
1080 EXPECT_LE(bytes_to_buffer_, total_bytes_written_); 1116 EXPECT_LE(bytes_to_buffer_, total_bytes_written_);
1081 } 1117 }
1082 1118
1083 } // anonymous namespace 1119 } // anonymous namespace
1084 1120
1085 } // namespace test 1121 } // namespace test
1086 1122
1087 } // namespace net 1123 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/core/quic_stream_sequencer_buffer.cc ('k') | net/quic/core/reliable_quic_stream.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698