Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // Histogram is an object that aggregates statistics, and can summarize them in | 5 // Histogram is an object that aggregates statistics, and can summarize them in |
| 6 // various forms, including ASCII graphical, HTML, and numerically (as a | 6 // various forms, including ASCII graphical, HTML, and numerically (as a |
| 7 // vector of numbers corresponding to each of the aggregating buckets). | 7 // vector of numbers corresponding to each of the aggregating buckets). |
| 8 // See header file for details and examples. | 8 // See header file for details and examples. |
| 9 | 9 |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| (...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 897 //------------------------------------------------------------------------------ | 897 //------------------------------------------------------------------------------ |
| 898 // The next section handles global (central) support for all histograms, as well | 898 // The next section handles global (central) support for all histograms, as well |
| 899 // as startup/teardown of this service. | 899 // as startup/teardown of this service. |
| 900 //------------------------------------------------------------------------------ | 900 //------------------------------------------------------------------------------ |
| 901 | 901 |
| 902 // This singleton instance should be started during the single threaded portion | 902 // This singleton instance should be started during the single threaded portion |
| 903 // of main(), and hence it is not thread safe. It initializes globals to | 903 // of main(), and hence it is not thread safe. It initializes globals to |
| 904 // provide support for all future calls. | 904 // provide support for all future calls. |
| 905 StatisticsRecorder::StatisticsRecorder() { | 905 StatisticsRecorder::StatisticsRecorder() { |
| 906 DCHECK(!histograms_); | 906 DCHECK(!histograms_); |
| 907 lock_ = new Lock; | 907 if (lock_ == NULL) |
| 908 lock_ = new Lock; | |
|
jar (doing other things)
2010/12/22 00:05:16
nit: Please add comment about the leak here, as th
MAD
2010/12/22 21:15:14
Done.
| |
| 909 AutoLock auto_lock(*lock_); | |
| 908 histograms_ = new HistogramMap; | 910 histograms_ = new HistogramMap; |
| 909 } | 911 } |
| 910 | 912 |
| 911 StatisticsRecorder::~StatisticsRecorder() { | 913 StatisticsRecorder::~StatisticsRecorder() { |
| 912 DCHECK(histograms_); | 914 DCHECK(histograms_ && lock_); |
| 913 | 915 |
| 914 if (dump_on_exit_) { | 916 if (dump_on_exit_) { |
| 915 std::string output; | 917 std::string output; |
| 916 WriteGraph("", &output); | 918 WriteGraph("", &output); |
| 917 LOG(INFO) << output; | 919 LOG(INFO) << output; |
| 918 } | 920 } |
| 919 // Clean up. | 921 // Clean up. |
| 920 delete histograms_; | 922 HistogramMap* histograms = NULL; |
| 921 histograms_ = NULL; | 923 { |
| 922 delete lock_; | 924 AutoLock auto_lock(*lock_); |
| 923 lock_ = NULL; | 925 histograms = histograms_; |
| 926 histograms_ = NULL; | |
| 927 } | |
| 928 delete histograms; | |
| 929 // We don't delete lock_ on purpose to avoid having to properly protect | |
| 930 // against it going away after we checked for NULL in the static methods. | |
| 924 } | 931 } |
| 925 | 932 |
| 926 // static | 933 // static |
| 927 bool StatisticsRecorder::WasStarted() { | 934 bool StatisticsRecorder::WasStarted() { |
| 935 if (lock_ == NULL) | |
| 936 return false; | |
| 937 AutoLock auto_lock(*lock_); | |
| 928 return NULL != histograms_; | 938 return NULL != histograms_; |
| 929 } | 939 } |
| 930 | 940 |
| 931 // Note: We can't accept a ref_ptr to |histogram| because we *might* not keep a | 941 // Note: We can't accept a ref_ptr to |histogram| because we *might* not keep a |
| 932 // reference, and we are called while in the Histogram constructor. In that | 942 // reference, and we are called while in the Histogram constructor. In that |
| 933 // scenario, a ref_ptr would have incremented the ref count when the histogram | 943 // scenario, a ref_ptr would have incremented the ref count when the histogram |
| 934 // was passed to us, decremented it when we returned, and the instance would be | 944 // was passed to us, decremented it when we returned, and the instance would be |
| 935 // destroyed before assignment (when value was returned by new). | 945 // destroyed before assignment (when value was returned by new). |
| 936 // static | 946 // static |
| 937 void StatisticsRecorder::Register(Histogram* histogram) { | 947 void StatisticsRecorder::Register(Histogram* histogram) { |
| 948 if (lock_ == NULL) | |
| 949 return; | |
| 950 AutoLock auto_lock(*lock_); | |
| 938 if (!histograms_) | 951 if (!histograms_) |
| 939 return; | 952 return; |
| 940 const std::string name = histogram->histogram_name(); | 953 const std::string name = histogram->histogram_name(); |
| 941 AutoLock auto_lock(*lock_); | |
| 942 // Avoid overwriting a previous registration. | 954 // Avoid overwriting a previous registration. |
| 943 if (histograms_->end() == histograms_->find(name)) | 955 if (histograms_->end() == histograms_->find(name)) |
| 944 (*histograms_)[name] = histogram; | 956 (*histograms_)[name] = histogram; |
| 945 } | 957 } |
| 946 | 958 |
| 947 // static | 959 // static |
| 948 void StatisticsRecorder::WriteHTMLGraph(const std::string& query, | 960 void StatisticsRecorder::WriteHTMLGraph(const std::string& query, |
| 949 std::string* output) { | 961 std::string* output) { |
| 950 if (!histograms_) | 962 if (lock_ == NULL) |
| 951 return; | 963 return; |
| 964 { | |
| 965 AutoLock auto_lock(*lock_); | |
| 966 if (!histograms_) | |
| 967 return; | |
| 968 } | |
|
jar (doing other things)
2010/12/22 00:05:16
nit: Please replace lines 962-968 with:
if (!WasSt
MAD
2010/12/22 21:15:14
Done.
| |
| 952 output->append("<html><head><title>About Histograms"); | 969 output->append("<html><head><title>About Histograms"); |
| 953 if (!query.empty()) | 970 if (!query.empty()) |
| 954 output->append(" - " + query); | 971 output->append(" - " + query); |
| 955 output->append("</title>" | 972 output->append("</title>" |
| 956 // We'd like the following no-cache... but it doesn't work. | 973 // We'd like the following no-cache... but it doesn't work. |
| 957 // "<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">" | 974 // "<META HTTP-EQUIV=\"Pragma\" CONTENT=\"no-cache\">" |
| 958 "</head><body>"); | 975 "</head><body>"); |
| 959 | 976 |
| 960 Histograms snapshot; | 977 Histograms snapshot; |
| 961 GetSnapshot(query, &snapshot); | 978 GetSnapshot(query, &snapshot); |
| 962 for (Histograms::iterator it = snapshot.begin(); | 979 for (Histograms::iterator it = snapshot.begin(); |
| 963 it != snapshot.end(); | 980 it != snapshot.end(); |
| 964 ++it) { | 981 ++it) { |
| 965 (*it)->WriteHTMLGraph(output); | 982 (*it)->WriteHTMLGraph(output); |
| 966 output->append("<br><hr><br>"); | 983 output->append("<br><hr><br>"); |
| 967 } | 984 } |
| 968 output->append("</body></html>"); | 985 output->append("</body></html>"); |
| 969 } | 986 } |
| 970 | 987 |
| 971 // static | 988 // static |
| 972 void StatisticsRecorder::WriteGraph(const std::string& query, | 989 void StatisticsRecorder::WriteGraph(const std::string& query, |
| 973 std::string* output) { | 990 std::string* output) { |
| 974 if (!histograms_) | 991 if (lock_ == NULL) |
| 975 return; | 992 return; |
| 993 { | |
| 994 AutoLock auto_lock(*lock_); | |
| 995 if (!histograms_) | |
| 996 return; | |
| 997 } | |
|
jar (doing other things)
2010/12/22 00:05:16
nit: Please replace lines 991-997 with:
if (!WasSt
MAD
2010/12/22 21:15:14
Done.
| |
| 976 if (query.length()) | 998 if (query.length()) |
| 977 StringAppendF(output, "Collections of histograms for %s\n", query.c_str()); | 999 StringAppendF(output, "Collections of histograms for %s\n", query.c_str()); |
| 978 else | 1000 else |
| 979 output->append("Collections of all histograms\n"); | 1001 output->append("Collections of all histograms\n"); |
| 980 | 1002 |
| 981 Histograms snapshot; | 1003 Histograms snapshot; |
| 982 GetSnapshot(query, &snapshot); | 1004 GetSnapshot(query, &snapshot); |
| 983 for (Histograms::iterator it = snapshot.begin(); | 1005 for (Histograms::iterator it = snapshot.begin(); |
| 984 it != snapshot.end(); | 1006 it != snapshot.end(); |
| 985 ++it) { | 1007 ++it) { |
| 986 (*it)->WriteAscii(true, "\n", output); | 1008 (*it)->WriteAscii(true, "\n", output); |
| 987 output->append("\n"); | 1009 output->append("\n"); |
| 988 } | 1010 } |
| 989 } | 1011 } |
| 990 | 1012 |
| 991 // static | 1013 // static |
| 992 void StatisticsRecorder::GetHistograms(Histograms* output) { | 1014 void StatisticsRecorder::GetHistograms(Histograms* output) { |
| 1015 if (lock_ == NULL) | |
| 1016 return; | |
| 1017 AutoLock auto_lock(*lock_); | |
| 993 if (!histograms_) | 1018 if (!histograms_) |
| 994 return; | 1019 return; |
| 995 AutoLock auto_lock(*lock_); | |
| 996 for (HistogramMap::iterator it = histograms_->begin(); | 1020 for (HistogramMap::iterator it = histograms_->begin(); |
| 997 histograms_->end() != it; | 1021 histograms_->end() != it; |
| 998 ++it) { | 1022 ++it) { |
| 999 DCHECK_EQ(it->first, it->second->histogram_name()); | 1023 DCHECK_EQ(it->first, it->second->histogram_name()); |
| 1000 output->push_back(it->second); | 1024 output->push_back(it->second); |
| 1001 } | 1025 } |
| 1002 } | 1026 } |
| 1003 | 1027 |
| 1004 bool StatisticsRecorder::FindHistogram(const std::string& name, | 1028 bool StatisticsRecorder::FindHistogram(const std::string& name, |
| 1005 scoped_refptr<Histogram>* histogram) { | 1029 scoped_refptr<Histogram>* histogram) { |
| 1030 if (lock_ == NULL) | |
| 1031 return false; | |
| 1032 AutoLock auto_lock(*lock_); | |
| 1006 if (!histograms_) | 1033 if (!histograms_) |
| 1007 return false; | 1034 return false; |
| 1008 AutoLock auto_lock(*lock_); | |
| 1009 HistogramMap::iterator it = histograms_->find(name); | 1035 HistogramMap::iterator it = histograms_->find(name); |
| 1010 if (histograms_->end() == it) | 1036 if (histograms_->end() == it) |
| 1011 return false; | 1037 return false; |
| 1012 *histogram = it->second; | 1038 *histogram = it->second; |
| 1013 return true; | 1039 return true; |
| 1014 } | 1040 } |
| 1015 | 1041 |
| 1016 // private static | 1042 // private static |
| 1017 void StatisticsRecorder::GetSnapshot(const std::string& query, | 1043 void StatisticsRecorder::GetSnapshot(const std::string& query, |
| 1018 Histograms* snapshot) { | 1044 Histograms* snapshot) { |
| 1045 if (lock_ == NULL) | |
| 1046 return; | |
| 1019 AutoLock auto_lock(*lock_); | 1047 AutoLock auto_lock(*lock_); |
| 1048 if (!histograms_) | |
| 1049 return; | |
| 1020 for (HistogramMap::iterator it = histograms_->begin(); | 1050 for (HistogramMap::iterator it = histograms_->begin(); |
| 1021 histograms_->end() != it; | 1051 histograms_->end() != it; |
| 1022 ++it) { | 1052 ++it) { |
| 1023 if (it->first.find(query) != std::string::npos) | 1053 if (it->first.find(query) != std::string::npos) |
| 1024 snapshot->push_back(it->second); | 1054 snapshot->push_back(it->second); |
| 1025 } | 1055 } |
| 1026 } | 1056 } |
| 1027 | 1057 |
| 1028 // static | 1058 // static |
| 1029 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; | 1059 StatisticsRecorder::HistogramMap* StatisticsRecorder::histograms_ = NULL; |
| 1030 // static | 1060 // static |
| 1031 Lock* StatisticsRecorder::lock_ = NULL; | 1061 Lock* StatisticsRecorder::lock_ = NULL; |
| 1032 // static | 1062 // static |
| 1033 bool StatisticsRecorder::dump_on_exit_ = false; | 1063 bool StatisticsRecorder::dump_on_exit_ = false; |
| 1034 | 1064 |
| 1035 } // namespace base | 1065 } // namespace base |
| OLD | NEW |