mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 01:36:09 +03:00
332 lines
13 KiB
C++
332 lines
13 KiB
C++
|
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#include <map>
|
||
|
#include <string>
|
||
|
|
||
|
#include "base/android/jni_android.h"
|
||
|
#include "base/android/jni_string.h"
|
||
|
#include "base/lazy_instance.h"
|
||
|
#include "base/macros.h"
|
||
|
#include "base/metrics/histogram.h"
|
||
|
#include "base/metrics/sparse_histogram.h"
|
||
|
#include "base/metrics/statistics_recorder.h"
|
||
|
#include "base/strings/stringprintf.h"
|
||
|
#include "base/synchronization/lock.h"
|
||
|
#include "base/time/time.h"
|
||
|
#include "jni/RecordHistogram_jni.h"
|
||
|
|
||
|
namespace base {
|
||
|
namespace android {
|
||
|
namespace {
|
||
|
|
||
|
// Simple thread-safe wrapper for caching histograms. This avoids
|
||
|
// relatively expensive JNI string translation for each recording.
|
||
|
class HistogramCache {
|
||
|
public:
|
||
|
HistogramCache() {}
|
||
|
|
||
|
std::string HistogramConstructionParamsToString(HistogramBase* histogram) {
|
||
|
std::string params_str = histogram->histogram_name();
|
||
|
switch (histogram->GetHistogramType()) {
|
||
|
case HISTOGRAM:
|
||
|
case LINEAR_HISTOGRAM:
|
||
|
case BOOLEAN_HISTOGRAM:
|
||
|
case CUSTOM_HISTOGRAM: {
|
||
|
Histogram* hist = static_cast<Histogram*>(histogram);
|
||
|
params_str += StringPrintf("/%d/%d/%d", hist->declared_min(),
|
||
|
hist->declared_max(), hist->bucket_count());
|
||
|
break;
|
||
|
}
|
||
|
case SPARSE_HISTOGRAM:
|
||
|
break;
|
||
|
}
|
||
|
return params_str;
|
||
|
}
|
||
|
|
||
|
void CheckHistogramArgs(JNIEnv* env,
|
||
|
jstring j_histogram_name,
|
||
|
int32_t expected_min,
|
||
|
int32_t expected_max,
|
||
|
uint32_t expected_bucket_count,
|
||
|
HistogramBase* histogram) {
|
||
|
std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
|
||
|
bool valid_arguments = Histogram::InspectConstructionArguments(
|
||
|
histogram_name, &expected_min, &expected_max, &expected_bucket_count);
|
||
|
DCHECK(valid_arguments);
|
||
|
DCHECK(histogram->HasConstructionArguments(expected_min, expected_max,
|
||
|
expected_bucket_count))
|
||
|
<< histogram_name << "/" << expected_min << "/" << expected_max << "/"
|
||
|
<< expected_bucket_count << " vs. "
|
||
|
<< HistogramConstructionParamsToString(histogram);
|
||
|
}
|
||
|
|
||
|
HistogramBase* BooleanHistogram(JNIEnv* env,
|
||
|
jstring j_histogram_name,
|
||
|
jlong j_histogram_key) {
|
||
|
DCHECK(j_histogram_name);
|
||
|
HistogramBase* histogram = HistogramFromKey(j_histogram_key);
|
||
|
if (histogram)
|
||
|
return histogram;
|
||
|
|
||
|
std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
|
||
|
histogram = BooleanHistogram::FactoryGet(
|
||
|
histogram_name, HistogramBase::kUmaTargetedHistogramFlag);
|
||
|
return histogram;
|
||
|
}
|
||
|
|
||
|
HistogramBase* EnumeratedHistogram(JNIEnv* env,
|
||
|
jstring j_histogram_name,
|
||
|
jlong j_histogram_key,
|
||
|
jint j_boundary) {
|
||
|
DCHECK(j_histogram_name);
|
||
|
HistogramBase* histogram = HistogramFromKey(j_histogram_key);
|
||
|
int32_t boundary = static_cast<int32_t>(j_boundary);
|
||
|
if (histogram) {
|
||
|
CheckHistogramArgs(env, j_histogram_name, 1, boundary, boundary + 1,
|
||
|
histogram);
|
||
|
return histogram;
|
||
|
}
|
||
|
|
||
|
std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
|
||
|
histogram =
|
||
|
LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1,
|
||
|
HistogramBase::kUmaTargetedHistogramFlag);
|
||
|
return histogram;
|
||
|
}
|
||
|
|
||
|
HistogramBase* CustomCountHistogram(JNIEnv* env,
|
||
|
jstring j_histogram_name,
|
||
|
jlong j_histogram_key,
|
||
|
jint j_min,
|
||
|
jint j_max,
|
||
|
jint j_num_buckets) {
|
||
|
DCHECK(j_histogram_name);
|
||
|
int32_t min = static_cast<int32_t>(j_min);
|
||
|
int32_t max = static_cast<int32_t>(j_max);
|
||
|
int32_t num_buckets = static_cast<int32_t>(j_num_buckets);
|
||
|
HistogramBase* histogram = HistogramFromKey(j_histogram_key);
|
||
|
if (histogram) {
|
||
|
CheckHistogramArgs(env, j_histogram_name, min, max, num_buckets,
|
||
|
histogram);
|
||
|
return histogram;
|
||
|
}
|
||
|
|
||
|
DCHECK_GE(min, 1) << "The min expected sample must be >= 1";
|
||
|
|
||
|
std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
|
||
|
histogram =
|
||
|
Histogram::FactoryGet(histogram_name, min, max, num_buckets,
|
||
|
HistogramBase::kUmaTargetedHistogramFlag);
|
||
|
return histogram;
|
||
|
}
|
||
|
|
||
|
HistogramBase* LinearCountHistogram(JNIEnv* env,
|
||
|
jstring j_histogram_name,
|
||
|
jlong j_histogram_key,
|
||
|
jint j_min,
|
||
|
jint j_max,
|
||
|
jint j_num_buckets) {
|
||
|
DCHECK(j_histogram_name);
|
||
|
int32_t min = static_cast<int32_t>(j_min);
|
||
|
int32_t max = static_cast<int32_t>(j_max);
|
||
|
int32_t num_buckets = static_cast<int32_t>(j_num_buckets);
|
||
|
HistogramBase* histogram = HistogramFromKey(j_histogram_key);
|
||
|
if (histogram) {
|
||
|
CheckHistogramArgs(env, j_histogram_name, min, max, num_buckets,
|
||
|
histogram);
|
||
|
return histogram;
|
||
|
}
|
||
|
|
||
|
std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
|
||
|
histogram =
|
||
|
LinearHistogram::FactoryGet(histogram_name, min, max, num_buckets,
|
||
|
HistogramBase::kUmaTargetedHistogramFlag);
|
||
|
return histogram;
|
||
|
}
|
||
|
|
||
|
HistogramBase* SparseHistogram(JNIEnv* env,
|
||
|
jstring j_histogram_name,
|
||
|
jlong j_histogram_key) {
|
||
|
DCHECK(j_histogram_name);
|
||
|
HistogramBase* histogram = HistogramFromKey(j_histogram_key);
|
||
|
if (histogram)
|
||
|
return histogram;
|
||
|
|
||
|
std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
|
||
|
histogram = SparseHistogram::FactoryGet(
|
||
|
histogram_name, HistogramBase::kUmaTargetedHistogramFlag);
|
||
|
return histogram;
|
||
|
}
|
||
|
|
||
|
HistogramBase* CustomTimesHistogram(JNIEnv* env,
|
||
|
jstring j_histogram_name,
|
||
|
jlong j_histogram_key,
|
||
|
jint j_min,
|
||
|
jint j_max,
|
||
|
jint j_bucket_count) {
|
||
|
DCHECK(j_histogram_name);
|
||
|
HistogramBase* histogram = HistogramFromKey(j_histogram_key);
|
||
|
int32_t min = static_cast<int32_t>(j_min);
|
||
|
int32_t max = static_cast<int32_t>(j_max);
|
||
|
int32_t bucket_count = static_cast<int32_t>(j_bucket_count);
|
||
|
if (histogram) {
|
||
|
CheckHistogramArgs(env, j_histogram_name, min, max, bucket_count,
|
||
|
histogram);
|
||
|
return histogram;
|
||
|
}
|
||
|
|
||
|
std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name);
|
||
|
// This intentionally uses FactoryGet and not FactoryTimeGet. FactoryTimeGet
|
||
|
// is just a convenience for constructing the underlying Histogram with
|
||
|
// TimeDelta arguments.
|
||
|
histogram = Histogram::FactoryGet(histogram_name, min, max, bucket_count,
|
||
|
HistogramBase::kUmaTargetedHistogramFlag);
|
||
|
return histogram;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
// Convert a jlong |histogram_key| from Java to a HistogramBase* via a cast.
|
||
|
// The Java side caches these in a map (see RecordHistogram.java), which is
|
||
|
// safe to do since C++ Histogram objects are never freed.
|
||
|
static HistogramBase* HistogramFromKey(jlong j_histogram_key) {
|
||
|
return reinterpret_cast<HistogramBase*>(j_histogram_key);
|
||
|
}
|
||
|
|
||
|
DISALLOW_COPY_AND_ASSIGN(HistogramCache);
|
||
|
};
|
||
|
|
||
|
LazyInstance<HistogramCache>::Leaky g_histograms;
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
jlong RecordBooleanHistogram(JNIEnv* env,
|
||
|
const JavaParamRef<jclass>& clazz,
|
||
|
const JavaParamRef<jstring>& j_histogram_name,
|
||
|
jlong j_histogram_key,
|
||
|
jboolean j_sample) {
|
||
|
bool sample = static_cast<bool>(j_sample);
|
||
|
HistogramBase* histogram = g_histograms.Get().BooleanHistogram(
|
||
|
env, j_histogram_name, j_histogram_key);
|
||
|
histogram->AddBoolean(sample);
|
||
|
return reinterpret_cast<jlong>(histogram);
|
||
|
}
|
||
|
|
||
|
jlong RecordEnumeratedHistogram(JNIEnv* env,
|
||
|
const JavaParamRef<jclass>& clazz,
|
||
|
const JavaParamRef<jstring>& j_histogram_name,
|
||
|
jlong j_histogram_key,
|
||
|
jint j_sample,
|
||
|
jint j_boundary) {
|
||
|
int sample = static_cast<int>(j_sample);
|
||
|
|
||
|
HistogramBase* histogram = g_histograms.Get().EnumeratedHistogram(
|
||
|
env, j_histogram_name, j_histogram_key, j_boundary);
|
||
|
histogram->Add(sample);
|
||
|
return reinterpret_cast<jlong>(histogram);
|
||
|
}
|
||
|
|
||
|
jlong RecordCustomCountHistogram(JNIEnv* env,
|
||
|
const JavaParamRef<jclass>& clazz,
|
||
|
const JavaParamRef<jstring>& j_histogram_name,
|
||
|
jlong j_histogram_key,
|
||
|
jint j_sample,
|
||
|
jint j_min,
|
||
|
jint j_max,
|
||
|
jint j_num_buckets) {
|
||
|
int sample = static_cast<int>(j_sample);
|
||
|
|
||
|
HistogramBase* histogram = g_histograms.Get().CustomCountHistogram(
|
||
|
env, j_histogram_name, j_histogram_key, j_min, j_max, j_num_buckets);
|
||
|
histogram->Add(sample);
|
||
|
return reinterpret_cast<jlong>(histogram);
|
||
|
}
|
||
|
|
||
|
jlong RecordLinearCountHistogram(JNIEnv* env,
|
||
|
const JavaParamRef<jclass>& clazz,
|
||
|
const JavaParamRef<jstring>& j_histogram_name,
|
||
|
jlong j_histogram_key,
|
||
|
jint j_sample,
|
||
|
jint j_min,
|
||
|
jint j_max,
|
||
|
jint j_num_buckets) {
|
||
|
int sample = static_cast<int>(j_sample);
|
||
|
|
||
|
HistogramBase* histogram = g_histograms.Get().LinearCountHistogram(
|
||
|
env, j_histogram_name, j_histogram_key, j_min, j_max, j_num_buckets);
|
||
|
histogram->Add(sample);
|
||
|
return reinterpret_cast<jlong>(histogram);
|
||
|
}
|
||
|
|
||
|
jlong RecordSparseHistogram(JNIEnv* env,
|
||
|
const JavaParamRef<jclass>& clazz,
|
||
|
const JavaParamRef<jstring>& j_histogram_name,
|
||
|
jlong j_histogram_key,
|
||
|
jint j_sample) {
|
||
|
int sample = static_cast<int>(j_sample);
|
||
|
HistogramBase* histogram = g_histograms.Get().SparseHistogram(
|
||
|
env, j_histogram_name, j_histogram_key);
|
||
|
histogram->Add(sample);
|
||
|
return reinterpret_cast<jlong>(histogram);
|
||
|
}
|
||
|
|
||
|
jlong RecordCustomTimesHistogramMilliseconds(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jclass>& clazz,
|
||
|
const JavaParamRef<jstring>& j_histogram_name,
|
||
|
jlong j_histogram_key,
|
||
|
jint j_duration,
|
||
|
jint j_min,
|
||
|
jint j_max,
|
||
|
jint j_num_buckets) {
|
||
|
HistogramBase* histogram = g_histograms.Get().CustomTimesHistogram(
|
||
|
env, j_histogram_name, j_histogram_key, j_min, j_max, j_num_buckets);
|
||
|
histogram->AddTime(
|
||
|
TimeDelta::FromMilliseconds(static_cast<int64_t>(j_duration)));
|
||
|
return reinterpret_cast<jlong>(histogram);
|
||
|
}
|
||
|
|
||
|
void Initialize(JNIEnv* env, const JavaParamRef<jclass>&) {
|
||
|
StatisticsRecorder::Initialize();
|
||
|
}
|
||
|
|
||
|
// This backs a Java test util for testing histograms -
|
||
|
// MetricsUtils.HistogramDelta. It should live in a test-specific file, but we
|
||
|
// currently can't have test-specific native code packaged in test-specific Java
|
||
|
// targets - see http://crbug.com/415945.
|
||
|
jint GetHistogramValueCountForTesting(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jclass>& clazz,
|
||
|
const JavaParamRef<jstring>& histogram_name,
|
||
|
jint sample) {
|
||
|
HistogramBase* histogram = StatisticsRecorder::FindHistogram(
|
||
|
android::ConvertJavaStringToUTF8(env, histogram_name));
|
||
|
if (histogram == nullptr) {
|
||
|
// No samples have been recorded for this histogram (yet?).
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
|
||
|
return samples->GetCount(static_cast<int>(sample));
|
||
|
}
|
||
|
|
||
|
jint GetHistogramTotalCountForTesting(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jclass>& clazz,
|
||
|
const JavaParamRef<jstring>& histogram_name) {
|
||
|
HistogramBase* histogram = StatisticsRecorder::FindHistogram(
|
||
|
android::ConvertJavaStringToUTF8(env, histogram_name));
|
||
|
if (histogram == nullptr) {
|
||
|
// No samples have been recorded for this histogram.
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return histogram->SnapshotSamples()->TotalCount();
|
||
|
}
|
||
|
|
||
|
} // namespace android
|
||
|
} // namespace base
|