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

Side by Side Diff: net/filter/brotli_stream_source.cc

Issue 1662763002: [ON HOLD] Implement pull-based design for content decoding (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix components_unittests Created 4 years, 5 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
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/filter/brotli_stream_source.h"
6
7 #include "base/bind.h"
8 #include "base/bit_cast.h"
9 #include "base/memory/ptr_util.h"
10 #include "base/metrics/histogram_macros.h"
11
12 namespace net {
13
14 namespace {
15
16 const char kBrotli[] = "br";
17
18 } // namespace
19
20 class BrotliStreamSource : public FilterStreamSource {
21 public:
22 BrotliStreamSource(std::unique_ptr<StreamSource> previous)
23 : FilterStreamSource(StreamSource::TYPE_BROTLI, std::move(previous)),
24 decoding_status_(DecodingStatus::DECODING_IN_PROGRESS),
25 used_memory_(0),
26 used_memory_maximum_(0),
27 produced_bytes_(0),
28 consumed_bytes_(0) {
29 brotli_state_ = BrotliCreateState(AllocateMemory, FreeMemory, this);
30 CHECK(brotli_state_);
31 }
32
33 ~BrotliStreamSource() override {
34 BrotliDestroyState(brotli_state_);
35 brotli_state_ = nullptr;
36 DCHECK(used_memory_ == 0);
37
38 UMA_HISTOGRAM_ENUMERATION(
39 "BrotliFilter.Status", static_cast<int>(decoding_status_),
eustas 2016/07/22 12:29:19 This file seems to be based on old version of brot
xunjieli 2016/07/27 20:32:04 Done. Thanks for letting me know. I've rebased thi
40 static_cast<int>(DecodingStatus::DECODING_STATUS_COUNT));
41 if (decoding_status_ == DecodingStatus::DECODING_DONE) {
42 // CompressionPercent is undefined when there is no output produced.
43 if (produced_bytes_ != 0) {
44 UMA_HISTOGRAM_PERCENTAGE(
45 "BrotliFilter.CompressionPercent",
46 static_cast<int>((consumed_bytes_ * 100) / produced_bytes_));
47 }
48 }
49 // All code here is for gathering stats, and can be removed when
50 // BrotliStreamSource is considered stable.
51 static const int kBuckets = 48;
52 static const int64_t kMaxKb = 1 << (kBuckets / 3); // 64MiB in KiB
53 UMA_HISTOGRAM_CUSTOM_COUNTS("BrotliFilter.UsedMemoryKB",
54 used_memory_maximum_ / 1024, 1, kMaxKb,
55 kBuckets);
56 }
57
58 private:
59 // Reported in UMA and must be kept in sync with the histograms.xml file.
60 enum class DecodingStatus : int {
61 DECODING_IN_PROGRESS = 0,
62 DECODING_DONE,
63 DECODING_ERROR,
64
65 DECODING_STATUS_COUNT
66 // DECODING_STATUS_COUNT must always be the last element in this enum.
67 };
68
69 // StreamSource implementation
70 std::string GetTypeAsString() const override { return kBrotli; }
71
72 int FilterData(IOBuffer* output_buffer,
73 size_t output_buffer_size,
74 DrainableIOBuffer* input_buffer) override {
75 const uint8_t* next_in = bit_cast<uint8_t*>(input_buffer->data());
76 size_t available_in = input_buffer->BytesRemaining();
77 uint8_t* next_out = bit_cast<uint8_t*>(output_buffer->data());
78 size_t available_out = output_buffer_size;
79 size_t total_out = 0;
80 BrotliResult result =
81 BrotliDecompressStream(&available_in, &next_in, &available_out,
82 &next_out, &total_out, brotli_state_);
83
84 size_t bytes_used = input_buffer->BytesRemaining() - available_in;
85 size_t bytes_written = output_buffer_size - available_out;
86 CHECK_GE(bytes_used, 0u);
87 CHECK_GE(bytes_written, 0u);
88 produced_bytes_ += bytes_written;
89 consumed_bytes_ += bytes_used;
90
91 input_buffer->DidConsume(bytes_used);
92
93 switch (result) {
94 case BROTLI_RESULT_NEEDS_MORE_OUTPUT:
95 // Fall through.
96 case BROTLI_RESULT_SUCCESS:
97 decoding_status_ = DecodingStatus::DECODING_DONE;
98 return bytes_written;
99 case BROTLI_RESULT_NEEDS_MORE_INPUT:
100 decoding_status_ = DecodingStatus::DECODING_IN_PROGRESS;
101 break;
102 // If the decompressor threw an error, fail synchronously.
103 default:
104 decoding_status_ = DecodingStatus::DECODING_ERROR;
105 return ERR_CONTENT_DECODING_FAILED;
106 }
107
108 DCHECK_EQ(BROTLI_RESULT_NEEDS_MORE_INPUT, result);
109 // Decompress needs more input has consumed all existing input.
110 DCHECK_EQ(0, input_buffer->BytesRemaining());
111
112 return bytes_written;
113 }
114
115 static void* AllocateMemory(void* opaque, size_t size) {
116 BrotliStreamSource* filter = reinterpret_cast<BrotliStreamSource*>(opaque);
117 return filter->AllocateMemoryInternal(size);
118 }
119
120 static void FreeMemory(void* opaque, void* address) {
121 BrotliStreamSource* filter = reinterpret_cast<BrotliStreamSource*>(opaque);
122 filter->FreeMemoryInternal(address);
123 }
124
125 void* AllocateMemoryInternal(size_t size) {
126 size_t* array = reinterpret_cast<size_t*>(malloc(size + sizeof(size_t)));
127 if (!array)
128 return nullptr;
129 used_memory_ += size;
130 if (used_memory_maximum_ < used_memory_)
131 used_memory_maximum_ = used_memory_;
132 array[0] = size;
133 return &array[1];
134 }
135
136 void FreeMemoryInternal(void* address) {
137 if (!address)
138 return;
139 size_t* array = reinterpret_cast<size_t*>(address);
140 used_memory_ -= array[-1];
141 free(&array[-1]);
142 }
143
144 BrotliState* brotli_state_;
145
146 DecodingStatus decoding_status_;
147
148 size_t used_memory_;
149 size_t used_memory_maximum_;
150 size_t produced_bytes_;
151 size_t consumed_bytes_;
152
153 DISALLOW_COPY_AND_ASSIGN(BrotliStreamSource);
154 };
155
156 std::unique_ptr<FilterStreamSource> CreateBrotliStreamSource(
157 std::unique_ptr<StreamSource> previous) {
158 return base::WrapUnique(new BrotliStreamSource(std::move(previous)));
159 }
160
161 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698