pluotsorbet/metrics.ts

209 строки
5.8 KiB
TypeScript

/*
* Copyright 2014 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
module J2ME.Metrics {
export class Timer {
private static _base: Timer = new Timer(null, "Total");
private static _top = Timer._base;
private static _flat = new Timer(null, "Flat");
private static _flatStack = [];
private _parent: Timer;
private _name: string;
private _begin: number;
private _last: number;
private _total: number;
private _count: number;
private _timers: Map<string, Timer>;
constructor(parent: Timer, name: string) {
this._parent = parent;
this._timers = ObjectUtilities.createMap<string, Timer>();
this._name = name;
this._begin = 0;
this._last = 0;
this._total = 0;
this._count = 0;
}
public static time(name, fn: Function) {
Timer.start(name);
fn();
Timer.stop();
}
public static start(name) {
Timer._top = Timer._top._timers[name] || (Timer._top._timers[name] = new Timer(Timer._top, name));
Timer._top.start();
var tmp = Timer._flat._timers[name] || (Timer._flat._timers[name] = new Timer(Timer._flat, name));
tmp.start();
Timer._flatStack.push(tmp);
}
public static stop() {
Timer._top.stop();
Timer._top = Timer._top._parent;
Timer._flatStack.pop().stop();
}
public static stopStart(name) {
Timer.stop();
Timer.start(name);
}
public start() {
this._begin = getTicks();
}
public stop() {
this._last = getTicks() - this._begin;
this._total += this._last;
this._count += 1;
}
public toJSON() {
return {name: this._name, total: this._total, timers: this._timers};
}
public trace(writer: IndentingWriter) {
writer.enter (
this._name + ": " + this._total.toFixed(2) + " ms" +
", count: " + this._count +
", average: " + (this._total / this._count).toFixed(2) + " ms"
);
for (var name in this._timers) {
this._timers[name].trace(writer);
}
writer.outdent();
}
public static trace(writer: IndentingWriter) {
Timer._base.trace(writer);
Timer._flat.trace(writer);
}
}
/**
* Quick way to count named events.
*/
export class Counter {
public static instance: Counter = new Counter(true);
private _enabled: boolean;
private _counts: Map<string, number>;
private _times: Map<string, number>;
get counts(): Map<string, number> {
return this._counts;
}
constructor(enabled: boolean) {
this._enabled = enabled;
this.clear();
}
public setEnabled(enabled:boolean) {
this._enabled = enabled;
}
public clear() {
this._counts = ObjectUtilities.createMap<string, number>();
this._times = ObjectUtilities.createMap<string, number>();
}
public toJSON() {
return {
counts: this._counts,
times: this._times
};
}
public count(name: string, increment: number = 1, time: number = 0) {
if (!this._enabled) {
return;
}
if (this._counts[name] === undefined) {
this._counts[name] = 0;
this._times[name] = 0;
}
this._counts[name] += increment;
this._times[name] += time;
return this._counts[name];
}
public trace(writer: IndentingWriter) {
for (var name in this._counts) {
writer.writeLn(name + ": " + this._counts[name]);
}
}
private _pairToString(times, pair): string {
var name = pair[0];
var count = pair[1];
var time = times[name];
var line = count + ": " + name;
if (time) {
line += ", " + time.toFixed(4);
if (count > 1) {
line += " (" + (time / count).toFixed(4) + ")";
}
}
return line;
}
public toStringSorted(): string {
var self = this;
var times = this._times;
var pairs = [];
for (var name in this._counts) {
pairs.push([name, this._counts[name]]);
}
pairs.sort(function (a, b) {
return b[1] - a[1];
});
return (pairs.map(function (pair) {
return self._pairToString(times, pair);
}).join(", "));
}
public traceSorted(writer: IndentingWriter, inline = false) {
var self = this;
var times = this._times;
var pairs = [];
for (var name in this._counts) {
pairs.push([name, this._counts[name]]);
}
pairs.sort(function (a, b) {
return b[1] - a[1];
});
if (inline) {
writer.writeLn(pairs.map(function (pair) {
return self._pairToString(times, pair);
}).join(", "));
} else {
pairs.forEach(function (pair) {
writer.writeLn(self._pairToString(times, pair));
});
}
}
}
export class Average {
private _samples: Float64Array;
private _count: number;
private _index: number;
constructor(max) {
this._samples = new Float64Array(max);
this._count = 0;
this._index = 0;
}
public push(sample: number) {
if (this._count < this._samples.length) {
this._count ++;
}
this._index ++;
this._samples[this._index % this._samples.length] = sample;
}
public average(): number {
var sum = 0;
for (var i = 0; i < this._count; i++) {
sum += this._samples[i];
}
return sum / this._count;
}
}
}