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

Unified Diff: net/spdy/spdy_header_block.cc

Issue 2611173004: Modify SpdyHeaderBlock's internals to consolidate header values only on first access. (Closed)
Patch Set: Rebase. Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/spdy/spdy_header_block.h ('k') | net/spdy/spdy_header_block_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/spdy/spdy_header_block.cc
diff --git a/net/spdy/spdy_header_block.cc b/net/spdy/spdy_header_block.cc
index 4e36b8927b57529a3c72405c2a95bdb51e01748f..6cbd6ba645c4585a3126099322effb3f9525c968 100644
--- a/net/spdy/spdy_header_block.cc
+++ b/net/spdy/spdy_header_block.cc
@@ -19,6 +19,7 @@
using base::StringPiece;
using std::dec;
using std::hex;
+using std::make_pair;
using std::max;
using std::min;
using std::string;
@@ -30,6 +31,16 @@ namespace {
const size_t kDefaultStorageBlockSize = 2048;
const char kCookieKey[] = "cookie";
+const char kNullSeparator = 0;
+
+StringPiece SeparatorForKey(StringPiece key) {
+ if (key == kCookieKey) {
+ static StringPiece cookie_separator = "; ";
+ return cookie_separator;
+ } else {
+ return StringPiece(&kNullSeparator, 1);
+ }
+}
} // namespace
@@ -50,24 +61,6 @@ class SpdyHeaderBlock::Storage {
return StringPiece(arena_.Memdup(s.data(), s.size()), s.size());
}
- // Given value, a string already in the arena, perform a realloc and append
- // separator and more to the end of the value's new location. If value is the
- // most recently added string (via Write), then UnsafeArena will not copy the
- // existing value but instead will increase the space reserved for value.
- StringPiece Realloc(StringPiece value,
- StringPiece separator,
- StringPiece more) {
- size_t total_length = value.size() + separator.size() + more.size();
- char* ptr = const_cast<char*>(value.data());
- ptr = arena_.Realloc(ptr, value.size(), total_length);
- StringPiece result(ptr, total_length);
- ptr += value.size();
- memcpy(ptr, separator.data(), separator.size());
- ptr += separator.size();
- memcpy(ptr, more.data(), more.size());
- return result;
- }
-
// If |s| points to the most recent allocation from arena_, the arena will
// reclaim the memory. Otherwise, this method is a no-op.
void Rewind(const StringPiece s) {
@@ -76,10 +69,77 @@ class SpdyHeaderBlock::Storage {
void Clear() { arena_.Reset(); }
+ // Given a list of fragments and a separator, writes the fragments joined by
+ // the separator to a contiguous region of memory. Returns a StringPiece
+ // pointing to the region of memory.
+ StringPiece WriteFragments(const std::vector<StringPiece>& fragments,
+ StringPiece separator) {
+ if (fragments.empty()) {
+ return StringPiece();
+ }
+ size_t total_size = separator.size() * (fragments.size() - 1);
+ for (const auto fragment : fragments) {
+ total_size += fragment.size();
+ }
+ char* dst = arena_.Alloc(total_size);
+ size_t written = Join(dst, fragments, separator);
+ DCHECK_EQ(written, total_size);
+ return StringPiece(dst, total_size);
+ }
+
+ size_t bytes_allocated() const { return arena_.status().bytes_allocated(); }
+
private:
UnsafeArena arena_;
};
+SpdyHeaderBlock::HeaderValue::HeaderValue(Storage* storage,
+ StringPiece key,
+ StringPiece initial_value)
+ : storage_(storage), fragments_({initial_value}), pair_({key, {}}) {}
+
+SpdyHeaderBlock::HeaderValue::HeaderValue(HeaderValue&& other)
+ : storage_(other.storage_),
+ fragments_(std::move(other.fragments_)),
+ pair_(std::move(other.pair_)) {}
+
+SpdyHeaderBlock::HeaderValue& SpdyHeaderBlock::HeaderValue::operator=(
+ HeaderValue&& other) {
+ storage_ = other.storage_;
+ fragments_ = std::move(other.fragments_);
+ pair_ = std::move(other.pair_);
+ return *this;
+}
+
+SpdyHeaderBlock::HeaderValue::~HeaderValue() {}
+
+StringPiece SpdyHeaderBlock::HeaderValue::ConsolidatedValue() const {
+ if (fragments_.empty()) {
+ return StringPiece();
+ }
+ if (fragments_.size() > 1) {
+ fragments_ = {
+ storage_->WriteFragments(fragments_, SeparatorForKey(pair_.first))};
+ }
+ return fragments_[0];
+}
+
+void SpdyHeaderBlock::HeaderValue::Append(StringPiece fragment) {
+ fragments_.push_back(fragment);
+}
+
+const std::pair<StringPiece, StringPiece>&
+SpdyHeaderBlock::HeaderValue::as_pair() const {
+ pair_.second = ConsolidatedValue();
+ return pair_;
+}
+
+SpdyHeaderBlock::iterator::iterator(MapType::const_iterator it) : it_(it) {}
+
+SpdyHeaderBlock::iterator::iterator(const iterator& other) : it_(other.it_) {}
+
+SpdyHeaderBlock::iterator::~iterator() {}
+
SpdyHeaderBlock::ValueProxy::ValueProxy(
SpdyHeaderBlock::MapType* block,
SpdyHeaderBlock::Storage* storage,
@@ -89,8 +149,7 @@ SpdyHeaderBlock::ValueProxy::ValueProxy(
storage_(storage),
lookup_result_(lookup_result),
key_(key),
- valid_(true) {
-}
+ valid_(true) {}
SpdyHeaderBlock::ValueProxy::ValueProxy(ValueProxy&& other)
: block_(other.block_),
@@ -127,10 +186,14 @@ SpdyHeaderBlock::ValueProxy& SpdyHeaderBlock::ValueProxy::operator=(
if (lookup_result_ == block_->end()) {
DVLOG(1) << "Inserting: (" << key_ << ", " << value << ")";
lookup_result_ =
- block_->insert(std::make_pair(key_, storage_->Write(value))).first;
+ block_
+ ->emplace(make_pair(
+ key_, HeaderValue(storage_, key_, storage_->Write(value))))
+ .first;
} else {
DVLOG(1) << "Updating key: " << key_ << " with value: " << value;
- lookup_result_->second = storage_->Write(value);
+ lookup_result_->second =
+ HeaderValue(storage_, key_, storage_->Write(value));
}
return *this;
}
@@ -139,7 +202,7 @@ string SpdyHeaderBlock::ValueProxy::as_string() const {
if (lookup_result_ == block_->end()) {
return "";
} else {
- return lookup_result_->second.as_string();
+ return lookup_result_->second.value().as_string();
}
}
@@ -160,8 +223,8 @@ SpdyHeaderBlock& SpdyHeaderBlock::operator=(SpdyHeaderBlock&& other) {
SpdyHeaderBlock SpdyHeaderBlock::Clone() const {
SpdyHeaderBlock copy;
- for (auto iter : *this) {
- copy.AppendHeader(iter.first, iter.second);
+ for (const auto& p : *this) {
+ copy.AppendHeader(p.first, p.second);
}
return copy;
}
@@ -181,7 +244,7 @@ string SpdyHeaderBlock::DebugString() const {
string output = "\n{\n";
for (auto it = begin(); it != end(); ++it) {
output +=
- " " + it->first.as_string() + ":" + it->second.as_string() + "\n";
+ " " + it->first.as_string() + " " + it->second.as_string() + "\n";
}
output.append("}\n");
return output;
@@ -192,8 +255,7 @@ void SpdyHeaderBlock::clear() {
storage_.reset();
}
-void SpdyHeaderBlock::insert(
- const SpdyHeaderBlock::MapType::value_type& value) {
+void SpdyHeaderBlock::insert(const SpdyHeaderBlock::value_type& value) {
// TODO(birenroy): Write new value in place of old value, if it fits.
auto iter = block_.find(value.first);
if (iter == block_.end()) {
@@ -202,7 +264,9 @@ void SpdyHeaderBlock::insert(
} else {
DVLOG(1) << "Updating key: " << iter->first
<< " with value: " << value.second;
- iter->second = GetStorage()->Write(value.second);
+ auto storage = GetStorage();
+ iter->second =
+ HeaderValue(storage, iter->first, storage->Write(value.second));
}
}
@@ -232,16 +296,15 @@ void SpdyHeaderBlock::AppendValueOrAddHeader(const StringPiece key,
return;
}
DVLOG(1) << "Updating key: " << iter->first << "; appending value: " << value;
- StringPiece separator("", 1);
- if (key == kCookieKey) {
- separator = "; ";
- }
- iter->second = GetStorage()->Realloc(iter->second, separator, value);
+ iter->second.Append(GetStorage()->Write(value));
}
void SpdyHeaderBlock::AppendHeader(const StringPiece key,
const StringPiece value) {
- block_.emplace(GetStorage()->Write(key), GetStorage()->Write(value));
+ auto storage = GetStorage();
+ auto backed_key = storage->Write(key);
+ block_.emplace(make_pair(
+ backed_key, HeaderValue(storage, backed_key, storage->Write(value))));
}
SpdyHeaderBlock::Storage* SpdyHeaderBlock::GetStorage() {
@@ -293,4 +356,31 @@ bool SpdyHeaderBlockFromNetLogParam(
return true;
}
+size_t SpdyHeaderBlock::bytes_allocated() const {
+ if (storage_ == nullptr) {
+ return 0;
+ } else {
+ return storage_->bytes_allocated();
+ }
+}
+
+size_t Join(char* dst,
+ const std::vector<StringPiece>& fragments,
+ StringPiece separator) {
+ if (fragments.empty()) {
+ return 0;
+ }
+ auto original_dst = dst;
+ auto it = fragments.begin();
+ memcpy(dst, it->data(), it->size());
+ dst += it->size();
+ for (++it; it != fragments.end(); ++it) {
+ memcpy(dst, separator.data(), separator.size());
+ dst += separator.size();
+ memcpy(dst, it->data(), it->size());
+ dst += it->size();
+ }
+ return dst - original_dst;
+}
+
} // namespace net
« no previous file with comments | « net/spdy/spdy_header_block.h ('k') | net/spdy/spdy_header_block_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698