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

Unified Diff: net/http/http_cache_transaction.cc

Issue 10808047: Add HttpCache histograms focussed on blocking and transaction type. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: catch more special cases Created 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/http_cache_transaction.cc
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 652a3b26b6d136d0a7fa3d8926deb9841f940582..80b5a8b3d099c7074576672dd4c7450bd493005d 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -41,6 +41,19 @@ using base::TimeTicks;
namespace net {
+namespace {
rvargas (doing something else) 2012/07/21 02:24:21 Move this outside of net
gavinp 2012/07/25 01:07:01 Done. You didn't say why: is it because it doesn't
rvargas (doing something else) 2012/07/25 19:41:04 In part because it's the common pattern everywhere
+
+// The cutoff for tagging small transactions in histograms; this size was chosen
+// to cover resources likely to be received in a single TCP window. With an
+// initial CWND of 10, and an MTU of 1500 bytes, with TCP and HTTP framing
+// overhead this is a size relatively likely to take only one RTT.
+const int kSmallResourceMaxBytes = 14 * 1024;
+
+// Requests faster than this do not report as many performance histograms.
+const int kFastRequestCutoffMs = 5;
+
+}
+
struct HeaderNameAndValue {
const char* name;
const char* value;
@@ -126,7 +139,8 @@ HttpCache::Transaction::Transaction(HttpCache* cache)
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(
base::Bind(&Transaction::OnIOComplete,
- weak_factory_.GetWeakPtr()))) {
+ weak_factory_.GetWeakPtr()))),
+ disposition_(DISPOSITION_UNDEFINED) {
COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders ==
arraysize(kValidationHeaders),
Invalid_number_of_validation_headers);
@@ -670,6 +684,8 @@ int HttpCache::Transaction::DoGetBackendComplete(int result) {
if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
mode_ = READ;
} else if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
+ // Don't record a load that isn't really testing the cache.
rvargas (doing something else) 2012/07/21 02:24:21 This goes through the cache.
gavinp 2012/07/25 01:07:01 Good point. Comment fixed. Srsly fixed.
+ MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
mode_ = WRITE;
} else {
mode_ = READ_WRITE;
@@ -718,6 +734,8 @@ int HttpCache::Transaction::DoSendRequest() {
DCHECK(mode_ & WRITE || mode_ == NONE);
DCHECK(!network_trans_.get());
+ started_reading_since_ = TimeTicks::Now();
rvargas (doing something else) 2012/07/21 02:24:21 The name is weird for what it is measuring.
gavinp 2012/07/25 01:07:01 Yup. Do you like the new name and use?
+
// Create a network transaction.
int rv = cache_->network_layer_->CreateTransaction(&network_trans_);
if (rv != OK)
@@ -737,6 +755,8 @@ int HttpCache::Transaction::DoSendRequestComplete(int result) {
return OK;
}
+ // Do not record requests that have network errors or restarts.
+ MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
if (IsCertificateError(result)) {
const HttpResponseInfo* response = network_trans_->GetResponseInfo();
// If we get a certificate error, then there is a certificate in ssl_info,
@@ -767,6 +787,7 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() {
// If we have an authentication response, we are exposed to weird things
// hapenning if the user cancels the authentication before we receive
// the new response.
+ MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
response_ = HttpResponseInfo();
network_trans_.reset();
new_response_ = NULL;
@@ -797,9 +818,11 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() {
// Are we expecting a response to a conditional query?
if (mode_ == READ_WRITE || mode_ == UPDATE) {
if (new_response->headers->response_code() == 304 || handling_206_) {
+ MaybeUpdateDisposition(DISPOSITION_ENTRY_VALIDATED_304);
rvargas (doing something else) 2012/07/21 02:24:21 This is more than just 304. Why not drop the 304 p
gavinp 2012/07/25 01:07:01 Done, the new more consistant names are good. Than
rvargas (doing something else) 2012/07/25 19:41:04 No other case, but to know that 206 doesn't matter
next_state_ = STATE_UPDATE_CACHED_RESPONSE;
return OK;
}
+ MaybeUpdateDisposition(DISPOSITION_ENTRY_VALIDATED_200);
rvargas (doing something else) 2012/07/21 02:24:21 What about names that match the histogram? used, v
gavinp 2012/07/25 01:07:01 Done.
mode_ = WRITE;
}
@@ -847,6 +870,7 @@ int HttpCache::Transaction::DoOpenEntry() {
next_state_ = STATE_OPEN_ENTRY_COMPLETE;
cache_pending_ = true;
net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
+ open_entry_since_ = TimeTicks::Now();
return cache_->OpenEntry(cache_key_, &new_entry_, this);
}
@@ -866,6 +890,7 @@ int HttpCache::Transaction::DoOpenEntryComplete(int result) {
return OK;
}
+ MaybeUpdateDisposition(DISPOSITION_NO_ENTRY);
if (request_->method == "PUT" || request_->method == "DELETE") {
DCHECK(mode_ == READ_WRITE || mode_ == WRITE);
mode_ = NONE;
@@ -1239,6 +1264,8 @@ int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
//
switch (mode_) {
case READ:
+ MaybeUpdateDisposition(DISPOSITION_ENTRY_UNCONDITIONALLY_USED);
+ started_reading_since_ = TimeTicks::Now();
rvargas (doing something else) 2012/07/21 02:24:21 Now I'm confused about what do you want to measure
gavinp 2012/07/25 01:07:01 You're right, it was too confusing. I came into th
result = BeginCacheRead();
break;
case READ_WRITE:
@@ -1346,12 +1373,17 @@ int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
if (!cache_)
return ERR_UNEXPECTED;
- if (partial_.get())
+ if (partial_.get()) {
+ // Partial requests are confusing to report in histograms because they may
+ // have multiple underlying requests.
+ MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
return DoPartialCacheReadCompleted(result);
+ }
if (result > 0) {
read_offset_ += result;
} else if (result == 0) { // End of file.
+ RecordHistograms(read_offset_);
cache_->DoneReadingFromEntry(entry_, this);
entry_ = NULL;
} else {
@@ -1499,6 +1531,7 @@ void HttpCache::Transaction::SetRequest(const BoundNetLog& net_log,
}
if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) {
+ MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
partial_.reset(new PartialData);
if (request_->method == "GET" && partial_->Init(request_->extra_headers)) {
// We will be modifying the actual range requested to the server, so
@@ -1570,13 +1603,19 @@ int HttpCache::Transaction::BeginCacheValidation() {
bool skip_validation = effective_load_flags_ & LOAD_PREFERRING_CACHE ||
!RequiresValidation();
- if (truncated_)
+ if (truncated_) {
+ // Truncated entries can cause partial gets, so we shouldn't record this
+ // load in histograms.
+ MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
skip_validation = !partial_->initial_validation();
+ }
if ((partial_.get() && !partial_->IsCurrentRangeCached()) || invalid_range_)
skip_validation = false;
if (skip_validation) {
+ MaybeUpdateDisposition(DISPOSITION_ENTRY_UNCONDITIONALLY_USED);
+ started_reading_since_ = TimeTicks::Now();
if (partial_.get()) {
// We are going to return the saved response headers to the caller, so
// we may need to adjust them first.
@@ -1594,6 +1633,7 @@ int HttpCache::Transaction::BeginCacheValidation() {
// Our mode remains READ_WRITE for a conditional request. We'll switch to
// either READ or WRITE mode once we hear back from the server.
if (!ConditionalizeRequest()) {
+ MaybeUpdateDisposition(DISPOSITION_ENTRY_UNCONDITIONALLY_USED);
DCHECK(!partial_.get());
DCHECK_NE(206, response_.headers->response_code());
mode_ = WRITE;
@@ -1610,6 +1650,8 @@ int HttpCache::Transaction::BeginPartialCacheValidation() {
!truncated_)
return BeginCacheValidation();
+ // Partial requests should not be recorded in histograms.
+ MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
if (range_requested_) {
next_state_ = STATE_CACHE_QUERY_DATA;
return OK;
@@ -1670,6 +1712,7 @@ int HttpCache::Transaction::BeginExternallyConditionalizedRequest() {
validator.empty() || validator != external_validation_.values[i]) {
// The externally conditionalized request is not a validation request
// for our existing cache entry. Proceed with caching disabled.
+ MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
DoneWritingToEntry(true);
}
}
@@ -1893,6 +1936,7 @@ bool HttpCache::Transaction::ValidatePartialResponse() {
if (failure) {
// We cannot truncate this entry, it has to be deleted.
+ MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
DoomPartialEntry(false);
mode_ = NONE;
if (!reading_ && !partial_->IsLastRange()) {
@@ -2015,9 +2059,11 @@ void HttpCache::Transaction::DoneWritingToEntry(bool success) {
if (!entry_)
return;
- if (cache_->mode() == RECORD)
+ RecordHistograms(entry_->disk_entry->GetDataSize(kResponseContentIndex));
+ if (cache_->mode() == RECORD) {
DVLOG(1) << "Recorded: " << request_->method << request_->url
rvargas (doing something else) 2012/07/21 02:24:21 unrelated: we should just delete this log.
gavinp 2012/07/25 01:07:01 Done.
<< " status: " << response_.headers->response_code();
+ }
cache_->DoneWritingToEntry(entry_, success);
entry_ = NULL;
@@ -2112,4 +2158,113 @@ void HttpCache::Transaction::OnIOComplete(int result) {
DoLoop(result);
}
+void HttpCache::Transaction::MaybeUpdateDisposition(
rvargas (doing something else) 2012/07/21 02:24:21 Remove the "maybe" part from the name.
gavinp 2012/07/25 01:07:01 Done.
+ const Disposition disposition) {
rvargas (doing something else) 2012/07/21 02:24:21 Drop the const
gavinp 2012/07/25 01:07:01 Done.
+ // Once a transaction has been found to have a complicated disposition, it
+ // can't change to any other simpler disposition.
+ if (disposition_ == DISPOSITION_DO_NOT_RECORD)
rvargas (doing something else) 2012/07/21 02:24:21 is this really worth the extra work?. We could jus
gavinp 2012/07/25 01:07:01 Done. Having both and the DCHECK was very good for
gavinp 2012/07/25 14:00:27 I should have updated this comment before uploadin
+ return;
+ DCHECK(disposition_ == DISPOSITION_UNDEFINED ||
+ disposition == DISPOSITION_DO_NOT_RECORD);
rvargas (doing something else) 2012/07/21 02:24:21 cannot reach do_not_record
gavinp 2012/07/25 01:07:01 Hrm, you are wrong. Does this mean I'm naming my p
rvargas (doing something else) 2012/07/25 19:41:04 Why am I wrong? the previous line returns if p_not
gavinp 2012/07/28 01:36:06 The previous line compares the member variable |di
+ disposition_ = disposition;
+}
+
+void HttpCache::Transaction::RecordHistograms(const int resource_size) {
rvargas (doing something else) 2012/07/21 02:24:21 Drop the const
gavinp 2012/07/25 01:07:01 Done.
+ if (cache_->mode() != NORMAL || request_->method != "GET")
+ return;
+
+ UMA_HISTOGRAM_BOOLEAN(
+ "HttpCache.DoNotRecord", disposition_ == DISPOSITION_DO_NOT_RECORD);
+ if (disposition_ == DISPOSITION_DO_NOT_RECORD)
+ return;
+ DCHECK(!range_requested_);
+ DCHECK_NE(DISPOSITION_UNDEFINED, disposition_);
gavinp 2012/07/20 17:19:24 Should these DCHECKs be changed into early returns
rvargas (doing something else) 2012/07/21 02:24:21 DCHECKS seem file to me.
gavinp 2012/07/25 01:07:01 What I found very interesting was how many differe
+ DCHECK(!open_entry_since_.is_null());
+ DCHECK(!started_reading_since_.is_null());
+
+ const TimeDelta before_reading_time =
rvargas (doing something else) 2012/07/21 02:24:21 I also think we should drop the const on these var
gavinp 2012/07/25 01:07:01 Done.
+ started_reading_since_ - open_entry_since_;
+ const TimeDelta reading_time = TimeTicks::Now() - started_reading_since_;
+ const TimeDelta total_time = before_reading_time + reading_time;
+
+ UMA_HISTOGRAM_TIMES("HttpCache.TimeBlocked", before_reading_time);
rvargas (doing something else) 2012/07/21 02:24:21 This puts together all cache types under the same
+ UMA_HISTOGRAM_TIMES("HttpCache.TimeReading", reading_time);
+
+ const bool is_small_resource = resource_size < kSmallResourceMaxBytes;
rvargas (doing something else) 2012/07/21 02:24:21 This is not what the caller is passing... I mean,
gavinp 2012/07/25 01:07:01 Good point. It's also undefined since I don't real
+ if (is_small_resource) {
+ UMA_HISTOGRAM_TIMES(
+ "HttpCache.TimeBlocked.SmallResource", before_reading_time);
rvargas (doing something else) 2012/07/21 02:24:21 nit: TimeBlocked?
+ UMA_HISTOGRAM_TIMES("HttpCache.TimeReading.SmallResource", reading_time);
+ }
+
+ // The more detailed histograms are only interesting for requests that are not
rvargas (doing something else) 2012/07/21 02:24:21 why?
gavinp 2012/07/25 01:07:01 Good point I had no reason whatsoever to actually
+ // fast.
+ if (total_time.InMilliseconds() < kFastRequestCutoffMs)
+ return;
+
+ const int before_reading_percent = before_reading_time * 100 / total_time;
+ DCHECK_LE(0, before_reading_percent);
+ DCHECK_GE(100, before_reading_percent);
+
+ UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBlocked", before_reading_percent);
rvargas (doing something else) 2012/07/21 02:24:21 nit: Not really blocked
gavinp 2012/07/25 01:07:01 Now named how long before send. The request isn't
+ if (is_small_resource)
+ UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBlocked.SmallResource",
+ before_reading_percent);
+
+ // TODO(gavinp): Remove or minimize these histograms, particularly the ones
+ // below this comment after we have received initial data.
+ switch (disposition_) {
rvargas (doing something else) 2012/07/21 02:24:21 nit: I'm not really happy with the term "dispositi
gavinp 2012/07/25 01:07:01 Now that you point it out, I hate the name too. T
+ case DISPOSITION_NO_ENTRY: {
+ UMA_HISTOGRAM_TIMES(
+ "HttpCache.TimeBlocked.NotCached", before_reading_time);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "HttpCache.PercentBlocked.NotCached", before_reading_percent);
rvargas (doing something else) 2012/07/21 02:24:21 Id suggest just dropping the absolute times.
gavinp 2012/07/25 01:07:01 You might be right. I'd like to wait for results.
+ if (is_small_resource) {
+ UMA_HISTOGRAM_PERCENTAGE(
+ "HttpCache.PercentBlocked.NotCached.SmallResource",
+ before_reading_percent);
+ }
+ break;
+ }
+ case DISPOSITION_ENTRY_UNCONDITIONALLY_USED: {
+ UMA_HISTOGRAM_TIMES(
+ "HttpCache.TimeBlocked.Used", before_reading_time);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "HttpCache.PercentBlocked.Used", before_reading_percent);
+ if (is_small_resource) {
+ UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBlocked.Used.SmallResource",
+ before_reading_percent);
+ }
+ break;
+ }
+ case DISPOSITION_ENTRY_VALIDATED_304: {
+ UMA_HISTOGRAM_TIMES(
+ "HttpCache.TimeBlocked.Validated", before_reading_time);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "HttpCache.PercentBlocked.Validated", before_reading_percent);
+ if (is_small_resource) {
+ UMA_HISTOGRAM_PERCENTAGE(
+ "HttpCache.PercentBlocked.Validated.SmallResource",
+ before_reading_percent);
+ }
+ break;
+ }
+ case DISPOSITION_ENTRY_VALIDATED_200: {
+ UMA_HISTOGRAM_TIMES(
+ "HttpCache.TimeBlocked.Updated", before_reading_time);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "HttpCache.PercentBlocked.Updated", before_reading_percent);
+ if (is_small_resource) {
+ UMA_HISTOGRAM_PERCENTAGE(
+ "HttpCache.PercentBlocked.Updated.SmallResource",
+ before_reading_percent);
+ }
+ break;
+ }
+ case DISPOSITION_UNDEFINED:
+ default:
+ NOTREACHED();
+ }
+}
+
} // namespace net
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698