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

Side by Side Diff: base/prefs/json_pref_store.cc

Issue 1083603002: Add histograms to record the number of writes to the prefs file (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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 | « base/prefs/json_pref_store.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "base/prefs/json_pref_store.h" 5 #include "base/prefs/json_pref_store.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
11 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
13 #include "base/json/json_file_value_serializer.h" 13 #include "base/json/json_file_value_serializer.h"
14 #include "base/json/json_string_value_serializer.h" 14 #include "base/json/json_string_value_serializer.h"
15 #include "base/memory/ref_counted.h" 15 #include "base/memory/ref_counted.h"
16 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
17 #include "base/prefs/pref_filter.h" 17 #include "base/prefs/pref_filter.h"
18 #include "base/sequenced_task_runner.h" 18 #include "base/sequenced_task_runner.h"
19 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
20 #include "base/task_runner_util.h" 21 #include "base/task_runner_util.h"
21 #include "base/threading/sequenced_worker_pool.h" 22 #include "base/threading/sequenced_worker_pool.h"
22 #include "base/values.h" 23 #include "base/values.h"
23 24
24 // Result returned from internal read tasks. 25 // Result returned from internal read tasks.
25 struct JsonPrefStore::ReadResult { 26 struct JsonPrefStore::ReadResult {
26 public: 27 public:
27 ReadResult(); 28 ReadResult();
28 ~ReadResult(); 29 ~ReadResult();
29 30
30 scoped_ptr<base::Value> value; 31 scoped_ptr<base::Value> value;
31 PrefReadError error; 32 PrefReadError error;
32 bool no_dir; 33 bool no_dir;
33 34
34 private: 35 private:
35 DISALLOW_COPY_AND_ASSIGN(ReadResult); 36 DISALLOW_COPY_AND_ASSIGN(ReadResult);
36 }; 37 };
37 38
38 JsonPrefStore::ReadResult::ReadResult() 39 JsonPrefStore::ReadResult::ReadResult()
39 : error(PersistentPrefStore::PREF_READ_ERROR_NONE), no_dir(false) { 40 : error(PersistentPrefStore::PREF_READ_ERROR_NONE), no_dir(false) {
40 } 41 }
41 42
42 JsonPrefStore::ReadResult::~ReadResult() { 43 JsonPrefStore::ReadResult::~ReadResult() {
43 } 44 }
44 45
46 // Represents a histogram which records the number of writes of the pref file
47 // that occured in a given time period.
48 class JsonPrefStore::WriteCountHistogram {
49 public:
50 WriteCountHistogram(
51 const base::TimeDelta& start_delay,
52 const base::TimeDelta& stop_delay,
53 const base::TimeDelta& commit_interval,
54 const base::FilePath& path,
55 const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner);
Mattias Nissler (ping if slow) 2015/04/14 11:58:27 Would be good to give this a name that makes it cl
56 ~WriteCountHistogram();
57 void RecordWriteOccured();
58
59 private:
60 void SendMetric();
61
62 // The time at which this object was constructed
63 base::Time creation_time_;
64
65 // The delay (after creation) before starting to record writes.
66 base::TimeDelta start_delay_;
67
68 // The delay (after creation) at which to stop recording writes.
69 base::TimeDelta stop_delay_;
70
71 // The minimum delay between writes of the pref file.
72 base::TimeDelta commit_interval_;
73
74 // The path to the pref file.
75 base::FilePath path_;
76
77 scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
78
79 // The total number of writes of the pref file in the interval recorded by
80 // this object.
81 uint32_t write_count_;
Mattias Nissler (ping if slow) 2015/04/14 11:58:27 Why not a plain int?
82
83 base::WeakPtrFactory<JsonPrefStore::WriteCountHistogram> weak_factory_;
84
85 DISALLOW_COPY_AND_ASSIGN(WriteCountHistogram);
86 };
87
45 namespace { 88 namespace {
46 89
47 // Some extensions we'll tack on to copies of the Preferences files. 90 // Some extensions we'll tack on to copies of the Preferences files.
48 const base::FilePath::CharType kBadExtension[] = FILE_PATH_LITERAL("bad"); 91 const base::FilePath::CharType kBadExtension[] = FILE_PATH_LITERAL("bad");
49 92
93 struct WriteCountHistogramInfo {
94 // The delay in minutes after startup at which to start recording write count
95 // data for this particular histogram.
96 int64_t start_delay;
Mattias Nissler (ping if slow) 2015/04/14 11:58:27 might want to call this start_delay_minutes for cl
97
98 // The delay in minutes after startup at which to stop recording write count
99 // data for this particular histogram.
100 int64_t stop_delay;
101 };
Mattias Nissler (ping if slow) 2015/04/14 11:58:27 Could make this an unnamed struct. If you don't, p
102 const WriteCountHistogramInfo kWriteCountHistograms[] = {
103 { 0, 1 }, // The first minute of writes.
104 { 1, 5 }, // The 2nd-5th minutes of writes.
105 { 5, 15 }, // The 6th-15th minutes of writes.
106 { 15, 60 }, // The 16th-60th minutes of writes.
107 };
108
50 PersistentPrefStore::PrefReadError HandleReadErrors( 109 PersistentPrefStore::PrefReadError HandleReadErrors(
51 const base::Value* value, 110 const base::Value* value,
52 const base::FilePath& path, 111 const base::FilePath& path,
53 int error_code, 112 int error_code,
54 const std::string& error_msg) { 113 const std::string& error_msg) {
55 if (!value) { 114 if (!value) {
56 DVLOG(1) << "Error while loading JSON file: " << error_msg 115 DVLOG(1) << "Error while loading JSON file: " << error_msg
57 << ", file: " << path.value(); 116 << ", file: " << path.value();
58 switch (error_code) { 117 switch (error_code) {
59 case JSONFileValueDeserializer::JSON_ACCESS_DENIED: 118 case JSONFileValueDeserializer::JSON_ACCESS_DENIED:
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 : path_(filename), 210 : path_(filename),
152 sequenced_task_runner_(sequenced_task_runner), 211 sequenced_task_runner_(sequenced_task_runner),
153 prefs_(new base::DictionaryValue()), 212 prefs_(new base::DictionaryValue()),
154 read_only_(false), 213 read_only_(false),
155 writer_(filename, sequenced_task_runner), 214 writer_(filename, sequenced_task_runner),
156 pref_filter_(pref_filter.Pass()), 215 pref_filter_(pref_filter.Pass()),
157 initialized_(false), 216 initialized_(false),
158 filtering_in_progress_(false), 217 filtering_in_progress_(false),
159 read_error_(PREF_READ_ERROR_NONE) { 218 read_error_(PREF_READ_ERROR_NONE) {
160 DCHECK(!path_.empty()); 219 DCHECK(!path_.empty());
220
221 for (size_t i = 0; i < sizeof(kWriteCountHistograms); ++i) {
222 write_count_histograms_.push_back(new WriteCountHistogram(
223 base::TimeDelta::FromMinutes(kWriteCountHistograms[i].start_delay),
224 base::TimeDelta::FromMinutes(kWriteCountHistograms[i].stop_delay),
225 writer_.commit_interval(),
226 path_,
227 sequenced_task_runner.get()));
228 }
161 } 229 }
162 230
163 JsonPrefStore::JsonPrefStore( 231 JsonPrefStore::JsonPrefStore(
164 const base::FilePath& filename, 232 const base::FilePath& filename,
165 const base::FilePath& alternate_filename, 233 const base::FilePath& alternate_filename,
166 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner, 234 const scoped_refptr<base::SequencedTaskRunner>& sequenced_task_runner,
167 scoped_ptr<PrefFilter> pref_filter) 235 scoped_ptr<PrefFilter> pref_filter)
168 : path_(filename), 236 : path_(filename),
169 alternate_path_(alternate_filename), 237 alternate_path_(alternate_filename),
170 sequenced_task_runner_(sequenced_task_runner), 238 sequenced_task_runner_(sequenced_task_runner),
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 } 455 }
388 } 456 }
389 457
390 JsonPrefStore::~JsonPrefStore() { 458 JsonPrefStore::~JsonPrefStore() {
391 CommitPendingWrite(); 459 CommitPendingWrite();
392 } 460 }
393 461
394 bool JsonPrefStore::SerializeData(std::string* output) { 462 bool JsonPrefStore::SerializeData(std::string* output) {
395 DCHECK(CalledOnValidThread()); 463 DCHECK(CalledOnValidThread());
396 464
465 for (WriteCountHistogram* histogram : write_count_histograms_)
466 histogram->RecordWriteOccured();
467
397 if (pref_filter_) 468 if (pref_filter_)
398 pref_filter_->FilterSerializeData(prefs_.get()); 469 pref_filter_->FilterSerializeData(prefs_.get());
399 470
400 JSONStringValueSerializer serializer(output); 471 JSONStringValueSerializer serializer(output);
401 // Not pretty-printing prefs shrinks pref file size by ~30%. To obtain 472 // Not pretty-printing prefs shrinks pref file size by ~30%. To obtain
402 // readable prefs for debugging purposes, you can dump your prefs into any 473 // readable prefs for debugging purposes, you can dump your prefs into any
403 // command-line or online JSON pretty printing tool. 474 // command-line or online JSON pretty printing tool.
404 serializer.set_pretty_print(false); 475 serializer.set_pretty_print(false);
405 return serializer.Serialize(*prefs_); 476 return serializer.Serialize(*prefs_);
406 } 477 }
(...skipping 21 matching lines...) Expand all
428 499
429 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE) 500 if (error_delegate_ && read_error_ != PREF_READ_ERROR_NONE)
430 error_delegate_->OnError(read_error_); 501 error_delegate_->OnError(read_error_);
431 502
432 FOR_EACH_OBSERVER(PrefStore::Observer, 503 FOR_EACH_OBSERVER(PrefStore::Observer,
433 observers_, 504 observers_,
434 OnInitializationCompleted(true)); 505 OnInitializationCompleted(true));
435 506
436 return; 507 return;
437 } 508 }
509
510 JsonPrefStore::WriteCountHistogram::WriteCountHistogram(
511 const base::TimeDelta& start_delay,
512 const base::TimeDelta& stop_delay,
513 const base::TimeDelta& commit_interval,
514 const base::FilePath& path,
515 const scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner)
516 : creation_time_(base::Time::Now()),
517 start_delay_(start_delay),
518 stop_delay_(stop_delay),
519 commit_interval_(commit_interval),
520 path_(path),
521 sequenced_task_runner_(sequenced_task_runner),
522 write_count_(0),
523 weak_factory_(this) {
524 sequenced_task_runner_->PostDelayedTask(FROM_HERE, base::Bind(
525 &JsonPrefStore::WriteCountHistogram::SendMetric,
526 weak_factory_.GetWeakPtr()), stop_delay_);
527 }
528
529 JsonPrefStore::WriteCountHistogram::~WriteCountHistogram() {}
530
531 void JsonPrefStore::WriteCountHistogram::RecordWriteOccured() {
532 base::Time current_time = base::Time::Now();
533 base::Time time_to_start = creation_time_ + start_delay_;
534 base::Time time_to_stop = creation_time_ + stop_delay_;
535 if (current_time >= time_to_start && current_time < time_to_stop)
536 ++write_count_;
Alexei Svitkine (slow) 2015/04/15 16:41:23 Can you add a DCHECK to ensure this doesn't get hi
raymes 2015/04/21 07:22:38 The design changed so this isn't an issue now.
537 }
538
539 void JsonPrefStore::WriteCountHistogram::SendMetric() {
540 std::string spaceless_basename;
541 base::ReplaceChars(path_.BaseName().MaybeAsASCII(), " ", "_",
542 &spaceless_basename);
543
544 std::string histogram_name =
545 "Settings.JsonDataWriteCount." + spaceless_basename + "_" +
Alexei Svitkine (slow) 2015/04/15 16:41:23 Please document these histograms in histograms.xml
raymes 2015/04/21 07:22:38 Done.
546 base::IntToString(start_delay_.InMinutes()) + "-" +
547 base::IntToString(stop_delay_.InMinutes());
548
549 // The min value for a histogram is 1. The max value is the maximum number of
550 // writes that can occur in the window being recorded. The max number of
551 // buckets used is 30 (plus the underflow/overflow buckets).
552 int32_t min_value = 1;
553 int32_t max_value = (stop_delay_ - start_delay_) / commit_interval_;
Mattias Nissler (ping if slow) 2015/04/14 11:58:27 This calculation doesn't work in the presence of P
554 int32_t num_buckets = std::min(max_value, 30) + 2;
555
556 // The histogram below is an expansion of the UMA_HISTOGRAM_CUSTOM_COUNTS
557 // macro adapted to allow for a dynamically suffixed histogram name.
558 // Note: The factory creates and owns the histogram.
559 base::HistogramBase* histogram = base::Histogram::FactoryGet(
560 histogram_name, min_value, max_value, num_buckets,
561 base::HistogramBase::kUmaTargetedHistogramFlag);
562 histogram->Add(write_count_);
563 }
OLDNEW
« no previous file with comments | « base/prefs/json_pref_store.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698