зеркало из https://github.com/mozilla/gecko-dev.git
bug 649502: Expose histograms to JS r=mrbkap
This commit is contained in:
Родитель
3ac76c1c9c
Коммит
5fba39075d
|
@ -283,6 +283,7 @@
|
|||
MODULE(jsperf) \
|
||||
SERVICES_CRYPTO_MODULE \
|
||||
MOZ_APP_COMPONENT_MODULES \
|
||||
MODULE(nsTelemetryModule) \
|
||||
/* end of list */
|
||||
|
||||
#define MODULE(_name) \
|
||||
|
|
|
@ -70,6 +70,7 @@ CPPSRCS = \
|
|||
nsStackWalk.cpp \
|
||||
nsMemoryReporterManager.cpp \
|
||||
FunctionTimer.cpp \
|
||||
nsTelemetry.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
@ -140,6 +141,7 @@ XPIDLSRCS = \
|
|||
nsIUUIDGenerator.idl \
|
||||
nsIMutable.idl \
|
||||
nsIMemoryReporter.idl \
|
||||
nsITelemetry.idl \
|
||||
$(NULL)
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
@ -152,6 +154,8 @@ FORCE_STATIC_LIB = 1
|
|||
# Force use of PIC
|
||||
FORCE_USE_PIC = 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
DEFINES += -D_IMPL_NS_COM
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Firefox.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation <http://www.mozilla.org>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Taras Glek <tglek@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(5c9afdb5-0532-47f3-be31-79e13a6db642)]
|
||||
interface nsITelemetry : nsISupports
|
||||
{
|
||||
/*
|
||||
* An object containing a snapshot from all of the currently registered histograms.
|
||||
* { name1: {data1}, name2:{data2}...}
|
||||
* where data is consists of the following properties:
|
||||
* min - Minimal bucket size
|
||||
* max - Maximum bucket size
|
||||
* histogram_type - 0:Exponential, 1:Linear
|
||||
* counts - array representing contents of the buckets in the histogram
|
||||
* ranges - an array with calculated bucket sizes
|
||||
* sum - sum of the bucket contents
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval histogramSnapshots;
|
||||
|
||||
/**
|
||||
* Create and return a histogram where bucket sizes increase exponentially. Parameters:
|
||||
* @param name Unique histogram name
|
||||
* @param min - Minimal bucket size
|
||||
* @param max - Maximum bucket size
|
||||
* @param bucket_count - number of buckets in the histogram.
|
||||
* The returned object has the following functions:
|
||||
* add(int) - Adds an int value to the appropriate bucket
|
||||
* snapshot() - Returns a snapshot of the histogram with the same data fields as in histogramSnapshots()
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
jsval newExponentialHistogram(in ACString name, in PRInt32 min, in PRInt32 max, in PRUint32 bucket_count);
|
||||
|
||||
/*
|
||||
Same as newExponentialHistogram, but for linear histograms
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
jsval newLinearHistogram(in ACString name, in PRInt32 min, in PRInt32 max, in PRUint32 bucket_count);
|
||||
};
|
|
@ -0,0 +1,233 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Taras Glek <tglek@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#define XPCOM_TRANSLATE_NSGM_ENTRY_POINT
|
||||
#include "base/histogram.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "jsapi.h"
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsITelemetry.h"
|
||||
|
||||
using namespace base;
|
||||
using namespace mozilla;
|
||||
|
||||
class Telemetry : public nsITelemetry
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITELEMETRY
|
||||
|
||||
public:
|
||||
static Telemetry* GetSingleton();
|
||||
};
|
||||
|
||||
// A static initializer to initialize histogram collection
|
||||
static StatisticsRecorder gStatisticsRecorder;
|
||||
|
||||
static bool
|
||||
FillRanges(JSContext *cx, JSObject *array, Histogram *h)
|
||||
{
|
||||
for (size_t i = 0;i < h->bucket_count();i++) {
|
||||
if (!JS_DefineElement(cx, array, i, INT_TO_JSVAL(h->ranges(i)), NULL, NULL, JSPROP_ENUMERATE))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ReflectHistogramSnapshot(JSContext *cx, JSObject *obj, Histogram *h)
|
||||
{
|
||||
Histogram::SampleSet ss;
|
||||
h->SnapshotSample(&ss);
|
||||
JSObject *counts_array;
|
||||
JSObject *rarray;
|
||||
const size_t count = h->bucket_count();
|
||||
if (!(JS_DefineProperty(cx, obj, "min", INT_TO_JSVAL(h->declared_min()), NULL, NULL, JSPROP_ENUMERATE)
|
||||
&& JS_DefineProperty(cx, obj, "max", INT_TO_JSVAL(h->declared_max()), NULL, NULL, JSPROP_ENUMERATE)
|
||||
&& JS_DefineProperty(cx, obj, "histogram_type", INT_TO_JSVAL(h->histogram_type()), NULL, NULL, JSPROP_ENUMERATE)
|
||||
&& JS_DefineProperty(cx, obj, "sum", INT_TO_JSVAL(ss.sum()), NULL, NULL, JSPROP_ENUMERATE)
|
||||
&& (rarray = JS_NewArrayObject(cx, count, NULL))
|
||||
&& JS_DefineProperty(cx, obj, "ranges", OBJECT_TO_JSVAL(rarray), NULL, NULL, JSPROP_ENUMERATE)
|
||||
&& FillRanges(cx, rarray, h)
|
||||
&& (counts_array = JS_NewArrayObject(cx, count, NULL))
|
||||
&& JS_DefineProperty(cx, obj, "counts", OBJECT_TO_JSVAL(counts_array), NULL, NULL, JSPROP_ENUMERATE)
|
||||
)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
for (size_t i = 0;i < count;i++) {
|
||||
if (!JS_DefineElement(cx, counts_array, i, INT_TO_JSVAL(ss.counts(i)), NULL, NULL, JSPROP_ENUMERATE)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JSHistogram_Add(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
jsval *argv = JS_ARGV(cx, vp);
|
||||
JSString *str;
|
||||
if (!JS_ConvertArguments(cx, argc, argv, "i", &str))
|
||||
return JS_FALSE;
|
||||
if (!JSVAL_IS_INT(argv[0]))
|
||||
return JS_FALSE;
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
Histogram *h = static_cast<Histogram*>(JS_GetPrivate(cx, obj));
|
||||
h->Add(JSVAL_TO_INT(argv[0]));
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
JSHistogram_Snapshot(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
Histogram *h = static_cast<Histogram*>(JS_GetPrivate(cx, obj));
|
||||
JSObject *snapshot = JS_NewObject(cx, NULL, NULL, NULL);
|
||||
if (!snapshot)
|
||||
return NS_ERROR_FAILURE;
|
||||
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(snapshot));
|
||||
return ReflectHistogramSnapshot(cx, snapshot, h);
|
||||
}
|
||||
|
||||
static nsresult
|
||||
WrapAndReturnHistogram(Histogram *h, JSContext *cx, jsval *ret)
|
||||
{
|
||||
static JSClass JSHistogram_class = {
|
||||
"JSHistogram", /* name */
|
||||
JSCLASS_HAS_PRIVATE, /* flags */
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
JSObject *obj = JS_NewObject(cx, &JSHistogram_class, NULL, NULL);
|
||||
if (!obj)
|
||||
return NS_ERROR_FAILURE;
|
||||
*ret = OBJECT_TO_JSVAL(obj);
|
||||
return (JS_SetPrivate(cx, obj, h)
|
||||
&& JS_DefineFunction (cx, obj, "add", JSHistogram_Add, 1, 0)
|
||||
&& JS_DefineFunction (cx, obj, "snapshot", JSHistogram_Snapshot, 1, 0)) ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telemetry::NewExponentialHistogram(const nsACString &name, PRInt32 min, PRInt32 max, PRUint32 size, JSContext *cx, jsval *ret)
|
||||
{
|
||||
Histogram *h = base::Histogram::FactoryGet(name.BeginReading(), min, max, size, base::Histogram::kNoFlags);
|
||||
return WrapAndReturnHistogram(h, cx, ret);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telemetry::NewLinearHistogram(const nsACString &name, PRInt32 min, PRInt32 max, PRUint32 size, JSContext *cx, jsval *ret)
|
||||
{
|
||||
Histogram *h = base::LinearHistogram::FactoryGet(name.BeginReading(), min, max, size, base::Histogram::kNoFlags);
|
||||
return WrapAndReturnHistogram(h, cx, ret);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Telemetry::GetHistogramSnapshots(JSContext *cx, jsval *ret)
|
||||
{
|
||||
JSObject *root_obj = JS_NewObject(cx, NULL, NULL, NULL);
|
||||
if (!root_obj)
|
||||
return NS_ERROR_FAILURE;
|
||||
*ret = OBJECT_TO_JSVAL(root_obj);
|
||||
|
||||
StatisticsRecorder::Histograms h;
|
||||
StatisticsRecorder::GetHistograms(&h);
|
||||
for (StatisticsRecorder::Histograms::iterator it = h.begin(); it != h.end();++it) {
|
||||
Histogram *h = *it;
|
||||
JSObject *hobj = JS_NewObject(cx, NULL, NULL, NULL);
|
||||
if (!(hobj
|
||||
&& JS_DefineProperty(cx, root_obj, h->histogram_name().c_str(),
|
||||
OBJECT_TO_JSVAL(hobj), NULL, NULL, JSPROP_ENUMERATE)
|
||||
&& ReflectHistogramSnapshot(cx, hobj, h))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(Telemetry, nsITelemetry)
|
||||
|
||||
static Telemetry *gJarHandler = nsnull;
|
||||
|
||||
static void ShutdownTelemetry()
|
||||
{
|
||||
NS_IF_RELEASE(gJarHandler);
|
||||
}
|
||||
|
||||
Telemetry* Telemetry::GetSingleton()
|
||||
{
|
||||
if (!gJarHandler) {
|
||||
gJarHandler = new Telemetry();
|
||||
NS_ADDREF(gJarHandler);
|
||||
}
|
||||
NS_ADDREF(gJarHandler);
|
||||
return gJarHandler;
|
||||
}
|
||||
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(Telemetry, Telemetry::GetSingleton)
|
||||
|
||||
#define NS_TELEMETRY_CID \
|
||||
{0xf880b792, 0xe6cd, 0x46e7, {0x9c, 0x22, 0x3e, 0x12, 0xc3, 0x8b, 0xc6, 0xca}}
|
||||
NS_DEFINE_NAMED_CID(NS_TELEMETRY_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry kTelemetryCIDs[] = {
|
||||
{ &kNS_TELEMETRY_CID, false, NULL, TelemetryConstructor },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const mozilla::Module::ContractIDEntry kTelemetryContracts[] = {
|
||||
{ "@mozilla.org/base/telemetry;1", &kNS_TELEMETRY_CID },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const mozilla::Module kTelemetryModule = {
|
||||
mozilla::Module::kVersion,
|
||||
kTelemetryCIDs,
|
||||
kTelemetryContracts,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
ShutdownTelemetry,
|
||||
};
|
||||
|
||||
NSMODULE_DEFN(nsTelemetryModule) = &kTelemetryModule;
|
|
@ -0,0 +1,38 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
const Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
|
||||
|
||||
function test_histogram(histogram_constructor, name, min, max, bucket_count) {
|
||||
var h = histogram_constructor(name, min, max, bucket_count);
|
||||
|
||||
var r = h.snapshot().ranges;
|
||||
var sum = 0;
|
||||
for(var i=0;i<r.length;i++) {
|
||||
var v = r[i];
|
||||
sum += v;
|
||||
h.add(v);
|
||||
}
|
||||
var s = h.snapshot();
|
||||
// verify sum
|
||||
do_check_eq(sum, h.snapshot().sum);;
|
||||
// there should be exactly one element per bucket
|
||||
for each(var i in s.counts) {
|
||||
do_check_eq(i, 1);
|
||||
}
|
||||
var hgrams = Telemetry.histogramSnapshots
|
||||
gh = hgrams[name]
|
||||
do_check_eq(gh.histogram_type,
|
||||
histogram_constructor == Telemetry.newExponentialHistogram ? 0 : 1);
|
||||
do_check_eq(gh.min, min)
|
||||
do_check_eq(gh.max, max)
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
test_histogram(Telemetry.newExponentialHistogram, "test::Exponential", 1, 10000, 10);
|
||||
test_histogram(Telemetry.newLinearHistogram, "test::Linear", 1, 10000, 10);
|
||||
}
|
Загрузка…
Ссылка в новой задаче