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

Side by Side Diff: net/sdch/sdch_owner.cc

Issue 1051353003: SDCH: add TimeWeightedMemoryUse (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Change metric denominator Created 5 years, 8 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/sdch/sdch_owner.h ('k') | net/sdch/sdch_owner_unittest.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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 4
5 #include "net/sdch/sdch_owner.h" 5 #include "net/sdch/sdch_owner.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/debug/alias.h" 8 #include "base/debug/alias.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/metrics/histogram_macros.h" 10 #include "base/metrics/histogram_macros.h"
11 #include "base/prefs/persistent_pref_store.h" 11 #include "base/prefs/persistent_pref_store.h"
12 #include "base/prefs/value_map_pref_store.h" 12 #include "base/prefs/value_map_pref_store.h"
13 #include "base/process/process_info.h"
13 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
14 #include "base/time/default_clock.h" 15 #include "base/time/default_clock.h"
15 #include "base/values.h" 16 #include "base/values.h"
16 #include "net/base/sdch_manager.h" 17 #include "net/base/sdch_manager.h"
17 #include "net/base/sdch_net_log_params.h" 18 #include "net/base/sdch_net_log_params.h"
18 19
19 namespace net { 20 namespace net {
20 21
21 namespace { 22 namespace {
22 23
23 enum DictionaryFate {
24 // A Get-Dictionary header wasn't acted on.
25 DICTIONARY_FATE_GET_IGNORED = 1,
26
27 // A fetch was attempted, but failed.
28 // TODO(rdsmith): Actually record this case.
29 DICTIONARY_FATE_FETCH_FAILED = 2,
30
31 // A successful fetch was dropped on the floor, no space.
32 DICTIONARY_FATE_FETCH_IGNORED_NO_SPACE = 3,
33
34 // A successful fetch was refused by the SdchManager.
35 DICTIONARY_FATE_FETCH_MANAGER_REFUSED = 4,
36
37 // A dictionary was successfully added based on
38 // a Get-Dictionary header in a response.
39 DICTIONARY_FATE_ADD_RESPONSE_TRIGGERED = 5,
40
41 // A dictionary was evicted by an incoming dict.
42 DICTIONARY_FATE_EVICT_FOR_DICT = 6,
43
44 // A dictionary was evicted by memory pressure.
45 DICTIONARY_FATE_EVICT_FOR_MEMORY = 7,
46
47 // A dictionary was evicted on destruction.
48 DICTIONARY_FATE_EVICT_FOR_DESTRUCTION = 8,
49
50 // A dictionary was successfully added based on
51 // persistence from a previous browser revision.
52 DICTIONARY_FATE_ADD_PERSISTENCE_TRIGGERED = 9,
53
54 // A dictionary was unloaded on destruction, but is still present on disk.
55 DICTIONARY_FATE_UNLOAD_FOR_DESTRUCTION = 10,
56
57 DICTIONARY_FATE_MAX = 11
58 };
59
60 enum PersistenceFailureReason { 24 enum PersistenceFailureReason {
61 // File didn't exist; is being created. 25 // File didn't exist; is being created.
62 PERSISTENCE_FAILURE_REASON_NO_FILE = 1, 26 PERSISTENCE_FAILURE_REASON_NO_FILE = 1,
63 27
64 // Error reading in information, but should be able to write. 28 // Error reading in information, but should be able to write.
65 PERSISTENCE_FAILURE_REASON_READ_FAILED = 2, 29 PERSISTENCE_FAILURE_REASON_READ_FAILED = 2,
66 30
67 // Error leading to abort on attempted persistence. 31 // Error leading to abort on attempted persistence.
68 PERSISTENCE_FAILURE_REASON_WRITE_FAILED = 3, 32 PERSISTENCE_FAILURE_REASON_WRITE_FAILED = 3,
69 33
70 PERSISTENCE_FAILURE_REASON_MAX = 4 34 PERSISTENCE_FAILURE_REASON_MAX = 4
71 }; 35 };
72 36
73 // Dictionaries that haven't been touched in 24 hours may be evicted 37 // Dictionaries that haven't been touched in 24 hours may be evicted
74 // to make room for new dictionaries. 38 // to make room for new dictionaries.
75 const int kFreshnessLifetimeHours = 24; 39 const int kFreshnessLifetimeHours = 24;
76 40
77 // Dictionaries that have never been used only stay fresh for one hour. 41 // Dictionaries that have never been used only stay fresh for one hour.
78 const int kNeverUsedFreshnessLifetimeHours = 1; 42 const int kNeverUsedFreshnessLifetimeHours = 1;
79 43
80 void RecordDictionaryFate(enum DictionaryFate fate) {
81 UMA_HISTOGRAM_ENUMERATION("Sdch3.DictionaryFate", fate, DICTIONARY_FATE_MAX);
82 }
83
84 void RecordPersistenceFailure(PersistenceFailureReason failure_reason) { 44 void RecordPersistenceFailure(PersistenceFailureReason failure_reason) {
85 UMA_HISTOGRAM_ENUMERATION("Sdch3.PersistenceFailureReason", failure_reason, 45 UMA_HISTOGRAM_ENUMERATION("Sdch3.PersistenceFailureReason", failure_reason,
86 PERSISTENCE_FAILURE_REASON_MAX); 46 PERSISTENCE_FAILURE_REASON_MAX);
87 } 47 }
88 48
89 void RecordDictionaryEvictionOrUnload(int use_count, DictionaryFate fate) {
90 DCHECK(fate == DICTIONARY_FATE_EVICT_FOR_DICT ||
91 fate == DICTIONARY_FATE_EVICT_FOR_MEMORY ||
92 fate == DICTIONARY_FATE_EVICT_FOR_DESTRUCTION ||
93 fate == DICTIONARY_FATE_UNLOAD_FOR_DESTRUCTION);
94
95 UMA_HISTOGRAM_COUNTS_100("Sdch3.DictionaryUseCount", use_count);
96 RecordDictionaryFate(fate);
97 }
98
99 // Schema specifications and access routines. 49 // Schema specifications and access routines.
100 50
101 // The persistent prefs store is conceptually shared with any other network 51 // The persistent prefs store is conceptually shared with any other network
102 // stack systems that want to persist data over browser restarts, and so 52 // stack systems that want to persist data over browser restarts, and so
103 // use of it must be namespace restricted. 53 // use of it must be namespace restricted.
104 // Schema: 54 // Schema:
105 // pref_store_->GetValue(kPreferenceName) -> Dictionary { 55 // pref_store_->GetValue(kPreferenceName) -> Dictionary {
106 // 'version' -> 1 [int] 56 // 'version' -> 1 [int]
107 // 'dictionaries' -> Dictionary { 57 // 'dictionaries' -> Dictionary {
108 // server_hash -> { 58 // server_hash -> {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 // static 209 // static
260 const size_t SdchOwner::kMaxTotalDictionarySize = 20 * 1000 * 1000; 210 const size_t SdchOwner::kMaxTotalDictionarySize = 20 * 1000 * 1000;
261 #endif 211 #endif
262 212
263 // Somewhat arbitrary, but we assume a dictionary smaller than 213 // Somewhat arbitrary, but we assume a dictionary smaller than
264 // 50K isn't going to do anyone any good. Note that this still doesn't 214 // 50K isn't going to do anyone any good. Note that this still doesn't
265 // prevent download and addition unless there is less than this 215 // prevent download and addition unless there is less than this
266 // amount of space available in storage. 216 // amount of space available in storage.
267 const size_t SdchOwner::kMinSpaceForDictionaryFetch = 50 * 1000; 217 const size_t SdchOwner::kMinSpaceForDictionaryFetch = 50 * 1000;
268 218
219 void SdchOwner::RecordDictionaryFate(enum DictionaryFate fate) {
220 UMA_HISTOGRAM_ENUMERATION("Sdch3.DictionaryFate", fate, DICTIONARY_FATE_MAX);
221 }
222
223 void SdchOwner::RecordDictionaryEvictionOrUnload(const std::string& server_hash,
224 size_t size,
225 int use_count,
226 DictionaryFate fate) {
227 DCHECK(fate == DICTIONARY_FATE_EVICT_FOR_DICT ||
228 fate == DICTIONARY_FATE_EVICT_FOR_MEMORY ||
229 fate == DICTIONARY_FATE_EVICT_FOR_DESTRUCTION ||
230 fate == DICTIONARY_FATE_UNLOAD_FOR_DESTRUCTION);
231
232 UMA_HISTOGRAM_COUNTS_100("Sdch3.DictionaryUseCount", use_count);
233 RecordDictionaryFate(fate);
234
235 DCHECK(load_times_.count(server_hash) == 1);
Randy Smith (Not in Mondays) 2015/04/03 20:36:51 If you're going to have this DCHECK, that suggests
236 base::Time now = clock_->Now();
237 base::TimeDelta dict_lifetime = now - load_times_[server_hash];
238 consumed_byte_seconds_.push_back(size * dict_lifetime.InMilliseconds());
239 }
240
269 SdchOwner::SdchOwner(SdchManager* sdch_manager, URLRequestContext* context) 241 SdchOwner::SdchOwner(SdchManager* sdch_manager, URLRequestContext* context)
270 : manager_(sdch_manager->GetWeakPtr()), 242 : manager_(sdch_manager->GetWeakPtr()),
271 fetcher_(new SdchDictionaryFetcher(context)), 243 fetcher_(new SdchDictionaryFetcher(context)),
272 total_dictionary_bytes_(0), 244 total_dictionary_bytes_(0),
273 clock_(new base::DefaultClock), 245 clock_(new base::DefaultClock),
274 max_total_dictionary_size_(kMaxTotalDictionarySize), 246 max_total_dictionary_size_(kMaxTotalDictionarySize),
275 min_space_for_dictionary_fetch_(kMinSpaceForDictionaryFetch), 247 min_space_for_dictionary_fetch_(kMinSpaceForDictionaryFetch),
276 #if defined(OS_CHROMEOS) 248 #if defined(OS_CHROMEOS)
277 // For debugging http://crbug.com/454198; remove when resolved. 249 // For debugging http://crbug.com/454198; remove when resolved.
278 destroyed_(0), 250 destroyed_(0),
(...skipping 23 matching lines...) Expand all
302 clock_.reset(); 274 clock_.reset();
303 CHECK(manager_.get()); 275 CHECK(manager_.get());
304 #endif 276 #endif
305 277
306 for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd(); 278 for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd();
307 it.Advance()) { 279 it.Advance()) {
308 int new_uses = it.use_count() - use_counts_at_load_[it.server_hash()]; 280 int new_uses = it.use_count() - use_counts_at_load_[it.server_hash()];
309 DictionaryFate fate = IsPersistingDictionaries() ? 281 DictionaryFate fate = IsPersistingDictionaries() ?
310 DICTIONARY_FATE_UNLOAD_FOR_DESTRUCTION : 282 DICTIONARY_FATE_UNLOAD_FOR_DESTRUCTION :
311 DICTIONARY_FATE_EVICT_FOR_DESTRUCTION; 283 DICTIONARY_FATE_EVICT_FOR_DESTRUCTION;
312 RecordDictionaryEvictionOrUnload(new_uses, fate); 284 RecordDictionaryEvictionOrUnload(it.server_hash(), it.size(), new_uses,
285 fate);
313 } 286 }
314 manager_->RemoveObserver(this); 287 manager_->RemoveObserver(this);
315 288
316 // This object only observes the external store during loading, 289 // This object only observes the external store during loading,
317 // i.e. before it's made the default preferences store. 290 // i.e. before it's made the default preferences store.
318 if (external_pref_store_) 291 if (external_pref_store_)
319 external_pref_store_->RemoveObserver(this); 292 external_pref_store_->RemoveObserver(this);
320 293
294 base::Time creation_time = base::CurrentProcessInfo::CreationTime();
Randy Smith (Not in Mondays) 2015/04/03 20:36:51 I'm still inclined to think this should just be th
295 int64 process_lifetime =
296 (clock_->Now() - creation_time).InMilliseconds();
297 for (auto& val : consumed_byte_seconds_) {
298 UMA_HISTOGRAM_COUNTS("Sdch3.TimeWeightedMemoryUse",
299 val / process_lifetime);
300 }
301
321 #if defined(OS_CHROMEOS) 302 #if defined(OS_CHROMEOS)
322 destroyed_ = 0xdeadbeef; 303 destroyed_ = 0xdeadbeef;
323 #endif 304 #endif
324 } 305 }
325 306
326 void SdchOwner::EnablePersistentStorage(PersistentPrefStore* pref_store) { 307 void SdchOwner::EnablePersistentStorage(PersistentPrefStore* pref_store) {
327 DCHECK(!external_pref_store_); 308 DCHECK(!external_pref_store_);
328 external_pref_store_ = pref_store; 309 external_pref_store_ = pref_store;
329 external_pref_store_->AddObserver(this); 310 external_pref_store_->AddObserver(this);
330 311
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 424
444 DCHECK(pref_dictionary_map->HasKey(stale_it->server_hash)); 425 DCHECK(pref_dictionary_map->HasKey(stale_it->server_hash));
445 bool success = pref_dictionary_map->RemoveWithoutPathExpansion( 426 bool success = pref_dictionary_map->RemoveWithoutPathExpansion(
446 stale_it->server_hash, nullptr); 427 stale_it->server_hash, nullptr);
447 DCHECK(success); 428 DCHECK(success);
448 429
449 avail_bytes += stale_it->dictionary_size; 430 avail_bytes += stale_it->dictionary_size;
450 431
451 int new_uses = stale_it->use_count - 432 int new_uses = stale_it->use_count -
452 use_counts_at_load_[stale_it->server_hash]; 433 use_counts_at_load_[stale_it->server_hash];
453 RecordDictionaryEvictionOrUnload(new_uses, 434 RecordDictionaryEvictionOrUnload(stale_it->server_hash,
435 stale_it->dictionary_size,
436 new_uses,
454 DICTIONARY_FATE_EVICT_FOR_DICT); 437 DICTIONARY_FATE_EVICT_FOR_DICT);
455 438
456 ++stale_it; 439 ++stale_it;
457 } 440 }
458 DCHECK_GE(avail_bytes, dictionary_text.size()); 441 DCHECK_GE(avail_bytes, dictionary_text.size());
459 442
460 RecordDictionaryFate( 443 RecordDictionaryFate(
461 // Distinguish between loads triggered by network responses and 444 // Distinguish between loads triggered by network responses and
462 // loads triggered by persistence. 445 // loads triggered by persistence.
463 last_used.is_null() ? DICTIONARY_FATE_ADD_RESPONSE_TRIGGERED 446 last_used.is_null() ? DICTIONARY_FATE_ADD_RESPONSE_TRIGGERED
(...skipping 16 matching lines...) Expand all
480 // Record the addition in the pref store. 463 // Record the addition in the pref store.
481 scoped_ptr<base::DictionaryValue> dictionary_description( 464 scoped_ptr<base::DictionaryValue> dictionary_description(
482 new base::DictionaryValue()); 465 new base::DictionaryValue());
483 dictionary_description->SetString(kDictionaryUrlKey, dictionary_url.spec()); 466 dictionary_description->SetString(kDictionaryUrlKey, dictionary_url.spec());
484 dictionary_description->SetDouble(kDictionaryLastUsedKey, 467 dictionary_description->SetDouble(kDictionaryLastUsedKey,
485 last_used.ToDoubleT()); 468 last_used.ToDoubleT());
486 dictionary_description->SetInteger(kDictionaryUseCountKey, use_count); 469 dictionary_description->SetInteger(kDictionaryUseCountKey, use_count);
487 dictionary_description->SetInteger(kDictionarySizeKey, 470 dictionary_description->SetInteger(kDictionarySizeKey,
488 dictionary_text.size()); 471 dictionary_text.size());
489 pref_dictionary_map->Set(server_hash, dictionary_description.Pass()); 472 pref_dictionary_map->Set(server_hash, dictionary_description.Pass());
473 load_times_[server_hash] = clock_->Now();
490 } 474 }
491 475
492 void SdchOwner::OnDictionaryUsed(SdchManager* manager, 476 void SdchOwner::OnDictionaryUsed(SdchManager* manager,
493 const std::string& server_hash) { 477 const std::string& server_hash) {
494 base::Time now(clock_->Now()); 478 base::Time now(clock_->Now());
495 base::DictionaryValue* pref_dictionary_map = 479 base::DictionaryValue* pref_dictionary_map =
496 GetPersistentStoreDictionaryMap(pref_store_); 480 GetPersistentStoreDictionaryMap(pref_store_);
497 ScopedPrefNotifier scoped_pref_notifier(pref_store_); 481 ScopedPrefNotifier scoped_pref_notifier(pref_store_);
498 482
499 base::Value* value = nullptr; 483 base::Value* value = nullptr;
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 fetcher_.reset(fetcher.release()); 696 fetcher_.reset(fetcher.release());
713 } 697 }
714 698
715 void SdchOwner::OnMemoryPressure( 699 void SdchOwner::OnMemoryPressure(
716 base::MemoryPressureListener::MemoryPressureLevel level) { 700 base::MemoryPressureListener::MemoryPressureLevel level) {
717 DCHECK_NE(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, level); 701 DCHECK_NE(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, level);
718 702
719 for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd(); 703 for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd();
720 it.Advance()) { 704 it.Advance()) {
721 int new_uses = it.use_count() - use_counts_at_load_[it.server_hash()]; 705 int new_uses = it.use_count() - use_counts_at_load_[it.server_hash()];
722 RecordDictionaryEvictionOrUnload(new_uses, 706 RecordDictionaryEvictionOrUnload(it.server_hash(),
707 it.size(),
708 new_uses,
723 DICTIONARY_FATE_EVICT_FOR_MEMORY); 709 DICTIONARY_FATE_EVICT_FOR_MEMORY);
724 } 710 }
725 711
726 // TODO(rdsmith): Make a distinction between moderate and critical 712 // TODO(rdsmith): Make a distinction between moderate and critical
727 // memory pressure. 713 // memory pressure.
728 manager_->ClearData(); 714 manager_->ClearData();
729 } 715 }
730 716
731 bool SdchOwner::SchedulePersistedDictionaryLoads( 717 bool SdchOwner::SchedulePersistedDictionaryLoads(
732 const base::DictionaryValue& persisted_info) { 718 const base::DictionaryValue& persisted_info) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 } 760 }
775 761
776 return true; 762 return true;
777 } 763 }
778 764
779 bool SdchOwner::IsPersistingDictionaries() const { 765 bool SdchOwner::IsPersistingDictionaries() const {
780 return in_memory_pref_store_.get() != nullptr; 766 return in_memory_pref_store_.get() != nullptr;
781 } 767 }
782 768
783 } // namespace net 769 } // namespace net
OLDNEW
« no previous file with comments | « net/sdch/sdch_owner.h ('k') | net/sdch/sdch_owner_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698