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

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: Record more exact creation time 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/strings/string_util.h" 13 #include "base/strings/string_util.h"
14 #include "base/time/default_clock.h" 14 #include "base/time/default_clock.h"
15 #include "base/values.h" 15 #include "base/values.h"
16 #include "net/base/sdch_manager.h" 16 #include "net/base/sdch_manager.h"
17 #include "net/base/sdch_net_log_params.h" 17 #include "net/base/sdch_net_log_params.h"
18 18
19 namespace net { 19 namespace net {
20 20
21 namespace { 21 namespace {
22 22
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 { 23 enum PersistenceFailureReason {
61 // File didn't exist; is being created. 24 // File didn't exist; is being created.
62 PERSISTENCE_FAILURE_REASON_NO_FILE = 1, 25 PERSISTENCE_FAILURE_REASON_NO_FILE = 1,
63 26
64 // Error reading in information, but should be able to write. 27 // Error reading in information, but should be able to write.
65 PERSISTENCE_FAILURE_REASON_READ_FAILED = 2, 28 PERSISTENCE_FAILURE_REASON_READ_FAILED = 2,
66 29
67 // Error leading to abort on attempted persistence. 30 // Error leading to abort on attempted persistence.
68 PERSISTENCE_FAILURE_REASON_WRITE_FAILED = 3, 31 PERSISTENCE_FAILURE_REASON_WRITE_FAILED = 3,
69 32
70 PERSISTENCE_FAILURE_REASON_MAX = 4 33 PERSISTENCE_FAILURE_REASON_MAX = 4
71 }; 34 };
72 35
73 // Dictionaries that haven't been touched in 24 hours may be evicted 36 // Dictionaries that haven't been touched in 24 hours may be evicted
74 // to make room for new dictionaries. 37 // to make room for new dictionaries.
75 const int kFreshnessLifetimeHours = 24; 38 const int kFreshnessLifetimeHours = 24;
76 39
77 // Dictionaries that have never been used only stay fresh for one hour. 40 // Dictionaries that have never been used only stay fresh for one hour.
78 const int kNeverUsedFreshnessLifetimeHours = 1; 41 const int kNeverUsedFreshnessLifetimeHours = 1;
79 42
80 void RecordDictionaryFate(enum DictionaryFate fate) {
81 UMA_HISTOGRAM_ENUMERATION("Sdch3.DictionaryFate", fate, DICTIONARY_FATE_MAX);
82 }
83
84 void RecordPersistenceFailure(PersistenceFailureReason failure_reason) { 43 void RecordPersistenceFailure(PersistenceFailureReason failure_reason) {
85 UMA_HISTOGRAM_ENUMERATION("Sdch3.PersistenceFailureReason", failure_reason, 44 UMA_HISTOGRAM_ENUMERATION("Sdch3.PersistenceFailureReason", failure_reason,
86 PERSISTENCE_FAILURE_REASON_MAX); 45 PERSISTENCE_FAILURE_REASON_MAX);
87 } 46 }
88 47
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. 48 // Schema specifications and access routines.
100 49
101 // The persistent prefs store is conceptually shared with any other network 50 // The persistent prefs store is conceptually shared with any other network
102 // stack systems that want to persist data over browser restarts, and so 51 // stack systems that want to persist data over browser restarts, and so
103 // use of it must be namespace restricted. 52 // use of it must be namespace restricted.
104 // Schema: 53 // Schema:
105 // pref_store_->GetValue(kPreferenceName) -> Dictionary { 54 // pref_store_->GetValue(kPreferenceName) -> Dictionary {
106 // 'version' -> 1 [int] 55 // 'version' -> 1 [int]
107 // 'dictionaries' -> Dictionary { 56 // 'dictionaries' -> Dictionary {
108 // server_hash -> { 57 // server_hash -> {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 // static 208 // static
260 const size_t SdchOwner::kMaxTotalDictionarySize = 20 * 1000 * 1000; 209 const size_t SdchOwner::kMaxTotalDictionarySize = 20 * 1000 * 1000;
261 #endif 210 #endif
262 211
263 // Somewhat arbitrary, but we assume a dictionary smaller than 212 // 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 213 // 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 214 // prevent download and addition unless there is less than this
266 // amount of space available in storage. 215 // amount of space available in storage.
267 const size_t SdchOwner::kMinSpaceForDictionaryFetch = 50 * 1000; 216 const size_t SdchOwner::kMinSpaceForDictionaryFetch = 50 * 1000;
268 217
218 void SdchOwner::RecordDictionaryFate(enum DictionaryFate fate) {
219 UMA_HISTOGRAM_ENUMERATION("Sdch3.DictionaryFate", fate, DICTIONARY_FATE_MAX);
220 }
221
222 void SdchOwner::RecordDictionaryEvictionOrUnload(const std::string& server_hash,
223 size_t size,
224 int use_count,
225 DictionaryFate fate) {
226 DCHECK(fate == DICTIONARY_FATE_EVICT_FOR_DICT ||
227 fate == DICTIONARY_FATE_EVICT_FOR_MEMORY ||
228 fate == DICTIONARY_FATE_EVICT_FOR_DESTRUCTION ||
229 fate == DICTIONARY_FATE_UNLOAD_FOR_DESTRUCTION);
230
231 UMA_HISTOGRAM_COUNTS_100("Sdch3.DictionaryUseCount", use_count);
232 RecordDictionaryFate(fate);
233
234 DCHECK(load_times_.count(server_hash) == 1);
235 base::Time now = clock_->Now();
236 base::TimeDelta dict_lifetime = now - load_times_[server_hash];
237 consumed_byte_seconds_.push_back(size * dict_lifetime.InMilliseconds());
238 }
239
269 SdchOwner::SdchOwner(SdchManager* sdch_manager, URLRequestContext* context) 240 SdchOwner::SdchOwner(SdchManager* sdch_manager, URLRequestContext* context)
270 : manager_(sdch_manager->GetWeakPtr()), 241 : manager_(sdch_manager->GetWeakPtr()),
271 fetcher_(new SdchDictionaryFetcher(context)), 242 fetcher_(new SdchDictionaryFetcher(context)),
272 total_dictionary_bytes_(0), 243 total_dictionary_bytes_(0),
273 clock_(new base::DefaultClock), 244 clock_(new base::DefaultClock),
274 max_total_dictionary_size_(kMaxTotalDictionarySize), 245 max_total_dictionary_size_(kMaxTotalDictionarySize),
275 min_space_for_dictionary_fetch_(kMinSpaceForDictionaryFetch), 246 min_space_for_dictionary_fetch_(kMinSpaceForDictionaryFetch),
276 #if defined(OS_CHROMEOS) 247 #if defined(OS_CHROMEOS)
277 // For debugging http://crbug.com/454198; remove when resolved. 248 // For debugging http://crbug.com/454198; remove when resolved.
278 destroyed_(0), 249 destroyed_(0),
279 #endif 250 #endif
280 memory_pressure_listener_( 251 memory_pressure_listener_(
281 base::Bind(&SdchOwner::OnMemoryPressure, 252 base::Bind(&SdchOwner::OnMemoryPressure,
282 // Because |memory_pressure_listener_| is owned by 253 // Because |memory_pressure_listener_| is owned by
283 // SdchOwner, the SdchOwner object will be available 254 // SdchOwner, the SdchOwner object will be available
284 // for the lifetime of |memory_pressure_listener_|. 255 // for the lifetime of |memory_pressure_listener_|.
285 base::Unretained(this))), 256 base::Unretained(this))),
286 in_memory_pref_store_(new ValueMapPrefStore()), 257 in_memory_pref_store_(new ValueMapPrefStore()),
287 external_pref_store_(nullptr), 258 external_pref_store_(nullptr),
288 pref_store_(in_memory_pref_store_.get()) { 259 pref_store_(in_memory_pref_store_.get()),
260 creation_time_(clock_->Now()) {
289 #if defined(OS_CHROMEOS) 261 #if defined(OS_CHROMEOS)
290 // For debugging http://crbug.com/454198; remove when resolved. 262 // For debugging http://crbug.com/454198; remove when resolved.
291 CHECK(clock_.get()); 263 CHECK(clock_.get());
292 #endif 264 #endif
293 manager_->AddObserver(this); 265 manager_->AddObserver(this);
294 InitializePrefStore(pref_store_); 266 InitializePrefStore(pref_store_);
295 } 267 }
296 268
297 SdchOwner::~SdchOwner() { 269 SdchOwner::~SdchOwner() {
298 #if defined(OS_CHROMEOS) 270 #if defined(OS_CHROMEOS)
299 // For debugging http://crbug.com/454198; remove when resolved. 271 // For debugging http://crbug.com/454198; remove when resolved.
300 CHECK_EQ(0u, destroyed_); 272 CHECK_EQ(0u, destroyed_);
301 CHECK(clock_.get()); 273 CHECK(clock_.get());
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 int64 process_lifetime =
295 (clock_->Now() - creation_time_).InMilliseconds();
296 for (auto& val : consumed_byte_seconds_) {
Ilya Sherman 2015/04/03 20:42:17 nit: "const auto&"?
297 UMA_HISTOGRAM_COUNTS("Sdch3.TimeWeightedMemoryUse",
298 val / process_lifetime);
Ilya Sherman 2015/04/03 20:42:17 Optional: Maybe use UMA_HISTOGRAM_MEMORY_KB here?
299 }
300
321 #if defined(OS_CHROMEOS) 301 #if defined(OS_CHROMEOS)
322 destroyed_ = 0xdeadbeef; 302 destroyed_ = 0xdeadbeef;
323 #endif 303 #endif
324 } 304 }
325 305
326 void SdchOwner::EnablePersistentStorage(PersistentPrefStore* pref_store) { 306 void SdchOwner::EnablePersistentStorage(PersistentPrefStore* pref_store) {
327 DCHECK(!external_pref_store_); 307 DCHECK(!external_pref_store_);
328 external_pref_store_ = pref_store; 308 external_pref_store_ = pref_store;
329 external_pref_store_->AddObserver(this); 309 external_pref_store_->AddObserver(this);
330 310
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 423
444 DCHECK(pref_dictionary_map->HasKey(stale_it->server_hash)); 424 DCHECK(pref_dictionary_map->HasKey(stale_it->server_hash));
445 bool success = pref_dictionary_map->RemoveWithoutPathExpansion( 425 bool success = pref_dictionary_map->RemoveWithoutPathExpansion(
446 stale_it->server_hash, nullptr); 426 stale_it->server_hash, nullptr);
447 DCHECK(success); 427 DCHECK(success);
448 428
449 avail_bytes += stale_it->dictionary_size; 429 avail_bytes += stale_it->dictionary_size;
450 430
451 int new_uses = stale_it->use_count - 431 int new_uses = stale_it->use_count -
452 use_counts_at_load_[stale_it->server_hash]; 432 use_counts_at_load_[stale_it->server_hash];
453 RecordDictionaryEvictionOrUnload(new_uses, 433 RecordDictionaryEvictionOrUnload(stale_it->server_hash,
434 stale_it->dictionary_size,
435 new_uses,
454 DICTIONARY_FATE_EVICT_FOR_DICT); 436 DICTIONARY_FATE_EVICT_FOR_DICT);
455 437
456 ++stale_it; 438 ++stale_it;
457 } 439 }
458 DCHECK_GE(avail_bytes, dictionary_text.size()); 440 DCHECK_GE(avail_bytes, dictionary_text.size());
459 441
460 RecordDictionaryFate( 442 RecordDictionaryFate(
461 // Distinguish between loads triggered by network responses and 443 // Distinguish between loads triggered by network responses and
462 // loads triggered by persistence. 444 // loads triggered by persistence.
463 last_used.is_null() ? DICTIONARY_FATE_ADD_RESPONSE_TRIGGERED 445 last_used.is_null() ? DICTIONARY_FATE_ADD_RESPONSE_TRIGGERED
(...skipping 16 matching lines...) Expand all
480 // Record the addition in the pref store. 462 // Record the addition in the pref store.
481 scoped_ptr<base::DictionaryValue> dictionary_description( 463 scoped_ptr<base::DictionaryValue> dictionary_description(
482 new base::DictionaryValue()); 464 new base::DictionaryValue());
483 dictionary_description->SetString(kDictionaryUrlKey, dictionary_url.spec()); 465 dictionary_description->SetString(kDictionaryUrlKey, dictionary_url.spec());
484 dictionary_description->SetDouble(kDictionaryLastUsedKey, 466 dictionary_description->SetDouble(kDictionaryLastUsedKey,
485 last_used.ToDoubleT()); 467 last_used.ToDoubleT());
486 dictionary_description->SetInteger(kDictionaryUseCountKey, use_count); 468 dictionary_description->SetInteger(kDictionaryUseCountKey, use_count);
487 dictionary_description->SetInteger(kDictionarySizeKey, 469 dictionary_description->SetInteger(kDictionarySizeKey,
488 dictionary_text.size()); 470 dictionary_text.size());
489 pref_dictionary_map->Set(server_hash, dictionary_description.Pass()); 471 pref_dictionary_map->Set(server_hash, dictionary_description.Pass());
472 load_times_[server_hash] = clock_->Now();
490 } 473 }
491 474
492 void SdchOwner::OnDictionaryUsed(SdchManager* manager, 475 void SdchOwner::OnDictionaryUsed(SdchManager* manager,
493 const std::string& server_hash) { 476 const std::string& server_hash) {
494 base::Time now(clock_->Now()); 477 base::Time now(clock_->Now());
495 base::DictionaryValue* pref_dictionary_map = 478 base::DictionaryValue* pref_dictionary_map =
496 GetPersistentStoreDictionaryMap(pref_store_); 479 GetPersistentStoreDictionaryMap(pref_store_);
497 ScopedPrefNotifier scoped_pref_notifier(pref_store_); 480 ScopedPrefNotifier scoped_pref_notifier(pref_store_);
498 481
499 base::Value* value = nullptr; 482 base::Value* value = nullptr;
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 fetcher_.reset(fetcher.release()); 695 fetcher_.reset(fetcher.release());
713 } 696 }
714 697
715 void SdchOwner::OnMemoryPressure( 698 void SdchOwner::OnMemoryPressure(
716 base::MemoryPressureListener::MemoryPressureLevel level) { 699 base::MemoryPressureListener::MemoryPressureLevel level) {
717 DCHECK_NE(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, level); 700 DCHECK_NE(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, level);
718 701
719 for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd(); 702 for (DictionaryPreferenceIterator it(pref_store_); !it.IsAtEnd();
720 it.Advance()) { 703 it.Advance()) {
721 int new_uses = it.use_count() - use_counts_at_load_[it.server_hash()]; 704 int new_uses = it.use_count() - use_counts_at_load_[it.server_hash()];
722 RecordDictionaryEvictionOrUnload(new_uses, 705 RecordDictionaryEvictionOrUnload(it.server_hash(),
706 it.size(),
707 new_uses,
723 DICTIONARY_FATE_EVICT_FOR_MEMORY); 708 DICTIONARY_FATE_EVICT_FOR_MEMORY);
724 } 709 }
725 710
726 // TODO(rdsmith): Make a distinction between moderate and critical 711 // TODO(rdsmith): Make a distinction between moderate and critical
727 // memory pressure. 712 // memory pressure.
728 manager_->ClearData(); 713 manager_->ClearData();
729 } 714 }
730 715
731 bool SdchOwner::SchedulePersistedDictionaryLoads( 716 bool SdchOwner::SchedulePersistedDictionaryLoads(
732 const base::DictionaryValue& persisted_info) { 717 const base::DictionaryValue& persisted_info) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 } 759 }
775 760
776 return true; 761 return true;
777 } 762 }
778 763
779 bool SdchOwner::IsPersistingDictionaries() const { 764 bool SdchOwner::IsPersistingDictionaries() const {
780 return in_memory_pref_store_.get() != nullptr; 765 return in_memory_pref_store_.get() != nullptr;
781 } 766 }
782 767
783 } // namespace net 768 } // 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