提交 01947566 编写于 作者: J Johannes Rieken

debt - remove unused TimeKeeper

上级 a0b67282
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.benchmarktimerbox {
z-index: 100;
position: absolute;
color: black;
background: lightblue;
top: 100px;
right: 20px;
font-family: monospace;
}
.benchmarktimerbox .inner {
width: 600px;
height: 300px;
overflow: scroll;
}
.benchmarktimerbox .timeFilter {
width: 50px;
}
.benchmarktimerbox pre {
margin: 0;
}
.timer-event-1 { background: rgba(190, 191, 193, 0.4); color: black; }
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./timer';
import { TimeKeeper, ITimerEvent, getTimeKeeper } from 'vs/base/common/timer';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import DomUtils = require('vs/base/browser/dom');
export class TimeKeeperRenderer {
private listenersToRemove: IDisposable[];
private timeKeeper: TimeKeeper;
private outerDomNode: HTMLElement;
private domNode: HTMLElement;
private renderCnt: number;
private lastEventIndex: number;
private textFilter: string;
private textFilterDomNode: HTMLInputElement;
private timeFilter: number;
private timeFilterDomNode: HTMLInputElement;
private intervalTokenId: number;
private renderedEvents: {
[key: string]: ITimerEvent;
};
private onHide: () => void;
constructor(onHide: () => void) {
this.timeKeeper = getTimeKeeper();
this.onHide = onHide;
this.lastEventIndex = 0;
this.renderedEvents = {};
this.renderCnt = 0;
this.listenersToRemove = [];
this.domNode = this._createDomNode();
this.intervalTokenId = window.setInterval(() => this._render(), 500);
}
public destroy(): void {
document.body.removeChild(this.outerDomNode);
window.clearInterval(this.intervalTokenId);
this.listenersToRemove = dispose(this.listenersToRemove);
}
private _createDomNode(): HTMLElement {
this.outerDomNode = document.createElement('div');
this.outerDomNode.className = 'benchmarktimerbox';
// Clear
let cancel: HTMLInputElement = <HTMLInputElement>document.createElement('input');
cancel.type = 'button';
cancel.value = 'Clear';
this.listenersToRemove.push(DomUtils.addDisposableListener(cancel, 'click', () => this._onClear()));
this.outerDomNode.appendChild(cancel);
// Text filter
this.textFilterDomNode = <HTMLInputElement>document.createElement('input');
this.textFilterDomNode.type = 'text';
this.textFilterDomNode.className = 'textFilter';
this.listenersToRemove.push(DomUtils.addDisposableListener(this.textFilterDomNode, 'keydown', () => this.onTextFilterChange()));
this.textFilter = '';
this.outerDomNode.appendChild(document.createTextNode('Filter'));
this.outerDomNode.appendChild(this.textFilterDomNode);
// Time filter
this.timeFilterDomNode = <HTMLInputElement>document.createElement('input');
this.timeFilterDomNode.type = 'text';
this.timeFilterDomNode.value = '0';
this.timeFilterDomNode.className = 'timeFilter';
this.listenersToRemove.push(DomUtils.addDisposableListener(this.timeFilterDomNode, 'keydown', () => this.onTimeFilterChange()));
this.timeFilter = 0;
this.outerDomNode.appendChild(document.createTextNode('Hide time under'));
this.outerDomNode.appendChild(this.timeFilterDomNode);
let hide: HTMLInputElement = <HTMLInputElement>document.createElement('input');
hide.type = 'button';
hide.value = 'Close';
this.listenersToRemove.push(DomUtils.addDisposableListener(hide, 'click', () => {
this.onHide();
}));
this.outerDomNode.appendChild(hide);
let heading = document.createElement('pre');
heading.appendChild(document.createTextNode(this.renderRow('TOPIC', 'NAME', 'TOOK', 'START', 'END')));
this.outerDomNode.appendChild(heading);
this.outerDomNode.appendChild(document.createElement('hr'));
let domNode = document.createElement('div');
domNode.className = 'inner';
this.outerDomNode.appendChild(domNode);
document.body.appendChild(this.outerDomNode);
return domNode;
}
private onTextFilterChange(): void {
setTimeout(() => {
this.refilter();
});
}
private onTimeFilterChange(): void {
setTimeout(() => {
this.refilter();
});
}
private matchesTextFilter(event: ITimerEvent): boolean {
if (!this.textFilter) {
return true;
}
if (event.topic.toLowerCase().indexOf(this.textFilter.toLowerCase()) >= 0) {
return true;
}
if (event.name.toLowerCase().indexOf(this.textFilter.toLowerCase()) >= 0) {
return true;
}
return false;
}
private matchesTimeFilter(event: ITimerEvent): boolean {
if (!this.timeFilter) {
return true;
}
if (event.timeTaken() >= this.timeFilter) {
return true;
}
return false;
}
private shouldShow(event: ITimerEvent): boolean {
return this.matchesTextFilter(event) && this.matchesTimeFilter(event);
}
private refilter(): void {
this.textFilter = this.textFilterDomNode.value;
this.timeFilter = parseInt(this.timeFilterDomNode.value, 10);
let domNodes = Array.prototype.slice.call(this.domNode.children, 0);
for (let i = 0; i < domNodes.length; i++) {
let eventId = domNodes[i].getAttribute('data-event-id');
let event = this.renderedEvents[eventId];
if (this.shouldShow(event)) {
domNodes[i].style.display = 'inherit';
} else {
domNodes[i].style.display = 'none';
}
}
}
private _onClear(): void {
this.lastEventIndex = this.timeKeeper.getCollectedEvents().length;
this.renderedEvents = {};
this.renderCnt = 0;
DomUtils.clearNode(this.domNode);
}
private leftPaddedString(size: number, padChar: string, str: string): string {
let spaces = this._repeatStr(padChar, Math.max(0, size - str.length));
return spaces + str;
}
private rightPaddedString(size: number, padChar: string, str: string): string {
let spaces = this._repeatStr(padChar, Math.max(0, size - str.length));
return str + spaces;
}
private renderRow(topic: string, name: string, timeTook: string, timeStart: string, timerEnd: string): string {
let result = ' ';
result += this.rightPaddedString(10, ' ', topic);
result += this.rightPaddedString(30, ' ', name);
result += ' ' + this.leftPaddedString(15, ' ', timeTook);
result += ' ' + this.leftPaddedString(13, ' ', timeStart);
return result;
}
private _suffix0(s: string): string {
if (s.charAt(s.length - 3) === '.') {
return s;
}
if (s.charAt(s.length - 2) === '.') {
return s + '0';
}
return s + '.00';
}
private _twoPrecision(a: number): string {
return this._suffix0(Math.round(a * 100) / 100 + '');
}
private _absoluteTime(t: number): string {
if (t < 1000) {
return this._twoPrecision(t) + ' ms';
}
t /= 1000;
if (t < 60) {
return this._twoPrecision(t) + ' s';
}
t /= 60;
if (t < 60) {
return this._twoPrecision(t) + ' m';
}
t /= 60;
return this._twoPrecision(t) + ' h';
}
private _renderEvent(domNode: HTMLElement, event: ITimerEvent): void {
let start = event.startTime.getTime() - TimeKeeper.PARSE_TIME.getTime();
let result = this.renderRow(
event.topic,
event.name,
this._twoPrecision(event.timeTaken()),
this._absoluteTime(start) + '',
this._absoluteTime(start + event.timeTaken())
);
domNode.textContent = '';
domNode.appendChild(document.createTextNode(result));
}
private _renderStartTimerEvent(event: ITimerEvent): void {
let domNode = document.createElement('pre');
this._renderEvent(domNode, event);
this.domNode.appendChild(domNode);
let idString = event.id.toString();
domNode.setAttribute('data-event-id', idString);
domNode.className = 'timer-event-' + (event.id % 2);
this.renderedEvents[idString] = event;
if (this.shouldShow(this.renderedEvents[idString])) {
domNode.style.display = 'inherit';
} else {
domNode.style.display = 'none';
}
this.renderCnt++;
}
private _render(): void {
let allEvents = this.timeKeeper.getCollectedEvents(), didSomething = false;
for (let i = this.lastEventIndex; i < allEvents.length; i++) {
let ev = allEvents[i];
if (!ev.stopTime) {
// This event is not yet finished => block
this.lastEventIndex = i;
if (didSomething) {
this.domNode.scrollTop = 100000;
}
return;
}
this._renderStartTimerEvent(ev);
didSomething = true;
}
if (didSomething) {
this.domNode.scrollTop = 100000;
}
this.lastEventIndex = allEvents.length;
}
private _repeatStr(str: string, cnt: number): string {
let r = '';
for (let i = 0; i < cnt; i++) {
r += str;
}
return r;
}
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import Platform = require('vs/base/common/platform');
import errors = require('vs/base/common/errors');
import precision = require('vs/base/common/stopwatch');
import { IDisposable } from 'vs/base/common/lifecycle';
export var ENABLE_TIMER = false;
var msWriteProfilerMark = Platform.globals['msWriteProfilerMark'];
export enum Topic {
EDITOR,
LANGUAGES,
WORKER,
WORKBENCH,
STARTUP
}
export interface ITimerEvent {
id: number;
topic: string;
name: string;
description: string;
data: any;
startTime: Date;
stopTime: Date;
stop(stopTime?: Date): void;
timeTaken(): number;
}
export interface IExistingTimerEvent {
topic: string;
name: string;
description?: string;
startTime: Date;
stopTime: Date;
}
class NullTimerEvent implements ITimerEvent {
public id: number;
public topic: string;
public name: string;
public description: string;
public data: any;
public startTime: Date;
public stopTime: Date;
public stop(): void {
return;
}
public timeTaken(): number {
return -1;
}
}
class TimerEvent implements ITimerEvent {
public id: number;
public topic: string;
public name: string;
public description: string;
public data: any;
public startTime: Date;
public stopTime: Date;
private timeKeeper: TimeKeeper;
private sw: precision.StopWatch;
constructor(timeKeeper: TimeKeeper, name: string, topic: string, startTime?: Date, description?: string) {
this.timeKeeper = timeKeeper;
this.name = name;
this.description = description;
this.topic = topic;
this.stopTime = null;
if (startTime) {
this.startTime = startTime;
return;
}
this.startTime = new Date();
this.sw = precision.StopWatch.create();
if (msWriteProfilerMark) {
var profilerName = ['Monaco', this.topic, this.name, 'start'];
msWriteProfilerMark(profilerName.join('|'));
}
}
public stop(stopTime?: Date): void {
// already stopped
if (this.stopTime !== null) {
return;
}
if (stopTime) {
this.stopTime = stopTime;
this.sw = null;
this.timeKeeper._onEventStopped(this);
return;
}
this.stopTime = new Date();
if (this.sw) {
this.sw.stop();
}
this.timeKeeper._onEventStopped(this);
if (msWriteProfilerMark) {
var profilerName = ['Monaco', this.topic, this.name, 'stop'];
msWriteProfilerMark(profilerName.join('|'));
}
}
public timeTaken(): number {
if (this.sw) {
return this.sw.elapsed();
}
if (this.stopTime) {
return this.stopTime.getTime() - this.startTime.getTime();
}
return -1;
}
}
export interface IEventsListener {
(events: ITimerEvent[]): void;
}
export class TimeKeeper {
/**
* After being started for 1 minute, all timers are automatically stopped.
*/
private static _MAX_TIMER_LENGTH = 60000; // 1 minute
/**
* Every 2 minutes, a sweep of current started timers is done.
*/
private static _CLEAN_UP_INTERVAL = 120000; // 2 minutes
/**
* Collect at most 1000 events.
*/
private static _EVENT_CACHE_LIMIT = 1000;
private static EVENT_ID = 1;
public static PARSE_TIME = new Date();
private cleaningIntervalId: Platform.IntervalToken;
private collectedEvents: ITimerEvent[];
private listeners: IEventsListener[];
constructor() {
this.cleaningIntervalId = -1;
this.collectedEvents = [];
this.listeners = [];
}
public isEnabled(): boolean {
return ENABLE_TIMER;
}
public start(topic: Topic | string, name: string, start?: Date, description?: string): ITimerEvent {
if (!this.isEnabled()) {
return nullEvent;
}
var strTopic: string;
if (typeof topic === 'string') {
strTopic = topic;
} else if (topic === Topic.EDITOR) {
strTopic = 'Editor';
} else if (topic === Topic.LANGUAGES) {
strTopic = 'Languages';
} else if (topic === Topic.WORKER) {
strTopic = 'Worker';
} else if (topic === Topic.WORKBENCH) {
strTopic = 'Workbench';
} else if (topic === Topic.STARTUP) {
strTopic = 'Startup';
}
this.initAutoCleaning();
var event = new TimerEvent(this, name, strTopic, start, description);
this.addEvent(event);
return event;
}
public dispose(): void {
if (this.cleaningIntervalId !== -1) {
Platform.clearInterval(this.cleaningIntervalId);
this.cleaningIntervalId = -1;
}
}
public addListener(listener: IEventsListener): IDisposable {
this.listeners.push(listener);
return {
dispose: () => {
for (var i = 0; i < this.listeners.length; i++) {
if (this.listeners[i] === listener) {
this.listeners.splice(i, 1);
return;
}
}
}
};
}
private addEvent(event: ITimerEvent): void {
event.id = TimeKeeper.EVENT_ID;
TimeKeeper.EVENT_ID++;
this.collectedEvents.push(event);
// expire items from the front of the cache
if (this.collectedEvents.length > TimeKeeper._EVENT_CACHE_LIMIT) {
this.collectedEvents.shift();
}
}
private initAutoCleaning(): void {
if (this.cleaningIntervalId === -1) {
this.cleaningIntervalId = Platform.setInterval(() => {
var now = Date.now();
this.collectedEvents.forEach((event) => {
if (!event.stopTime && (now - event.startTime.getTime()) >= TimeKeeper._MAX_TIMER_LENGTH) {
event.stop();
}
});
}, TimeKeeper._CLEAN_UP_INTERVAL);
}
}
public getCollectedEvents(): ITimerEvent[] {
return this.collectedEvents.slice(0);
}
public clearCollectedEvents(): void {
this.collectedEvents = [];
}
_onEventStopped(event: ITimerEvent): void {
var emitEvents = [event];
var listeners = this.listeners.slice(0);
for (var i = 0; i < listeners.length; i++) {
try {
listeners[i](emitEvents);
} catch (e) {
errors.onUnexpectedError(e);
}
}
}
public setInitialCollectedEvents(events: IExistingTimerEvent[], startTime?: Date): void {
if (!this.isEnabled()) {
return;
}
if (startTime) {
TimeKeeper.PARSE_TIME = startTime;
}
events.forEach((event) => {
var e = new TimerEvent(this, event.name, event.topic, event.startTime, event.description);
e.stop(event.stopTime);
this.addEvent(e);
});
}
}
var timeKeeper = new TimeKeeper();
export var nullEvent: ITimerEvent = new NullTimerEvent();
export function start(topic: Topic | string, name: string, start?: Date, description?: string): ITimerEvent {
return timeKeeper.start(topic, name, start, description);
}
export function getTimeKeeper(): TimeKeeper {
return timeKeeper;
}
......@@ -7,7 +7,6 @@
import { onUnexpectedError } from 'vs/base/common/errors';
import { EmitterEvent, IEventEmitter } from 'vs/base/common/eventEmitter';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import * as timer from 'vs/base/common/timer';
import * as browser from 'vs/base/browser/browser';
import * as dom from 'vs/base/browser/dom';
import { StyleMutator } from 'vs/base/browser/styleMutator';
......@@ -899,14 +898,12 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
if (!dom.isInDOM(this.domNode)) {
return;
}
let t = timer.start(timer.Topic.EDITOR, 'View.render');
let viewPartsToRender = this._getViewPartsToRender();
if (!this.viewLines.shouldRender() && viewPartsToRender.length === 0) {
// Nothing to render
this.keyboardHandler.writeToTextArea();
t.stop();
return;
}
......@@ -940,8 +937,6 @@ export class View extends ViewEventHandler implements editorBrowser.IView, IDisp
// Render the scrollbar
this.layoutProvider.renderScrollbar();
t.stop();
}
private _setHasFocus(newHasFocus: boolean): void {
......
......@@ -8,7 +8,6 @@ import * as nls from 'vs/nls';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDisposable } from 'vs/base/common/lifecycle';
import { StopWatch } from 'vs/base/common/stopwatch';
import * as timer from 'vs/base/common/timer';
import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { TextModel } from 'vs/editor/common/model/textModel';
......@@ -294,7 +293,6 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke
this._withModelTokensChangedEventBuilder((eventBuilder) => {
var t1 = timer.start(timer.Topic.EDITOR, 'backgroundTokenization');
toLineNumber = Math.min(this._lines.length, toLineNumber);
var MAX_ALLOWED_TIME = 20,
......@@ -342,8 +340,6 @@ export class TextModelWithTokens extends TextModel implements editorCommon.IToke
if (this._invalidLineStartIndex < this._lines.length) {
this._beginBackgroundTokenization();
}
t1.stop();
});
}
......
......@@ -14,7 +14,6 @@ import { domContentLoaded } from 'vs/base/browser/dom';
import errors = require('vs/base/common/errors');
import platform = require('vs/base/common/platform');
import paths = require('vs/base/common/paths');
import timer = require('vs/base/common/timer');
import uri from 'vs/base/common/uri';
import strings = require('vs/base/common/strings');
import { IResourceInput } from 'vs/platform/editor/common/editor';
......@@ -62,10 +61,6 @@ export function startup(configuration: IWindowConfiguration): TPromise<void> {
filesToDiff
};
if (configuration.performance) {
timer.ENABLE_TIMER = true;
}
// Resolve workspace
return getWorkspace(configuration.workspacePath).then(workspace => {
......@@ -171,4 +166,4 @@ function loaderError(err: Error): Error {
}
return new Error(nls.localize('loaderErrorNative', "Failed to load a required file. Please restart the application to try again. Details: {0}", JSON.stringify(err)));
}
\ No newline at end of file
}
......@@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as timer from 'vs/base/common/timer';
import paths = require('vs/base/common/paths');
import objects = require('vs/base/common/objects');
import strings = require('vs/base/common/strings');
......@@ -544,14 +543,12 @@ export class SearchModel extends Disposable {
this._searchResult.query = this._searchQuery.contentPattern;
this._replacePattern = new ReplacePattern(this._replaceString, this._searchQuery.contentPattern);
const timerEvent = timer.start(timer.Topic.WORKBENCH, 'Search');
this.currentRequest = this.searchService.search(this._searchQuery);
const onDone = fromPromise(this.currentRequest);
const onDoneStopwatch = stopwatch(onDone);
const start = Date.now();
onDone(() => timerEvent.stop());
onDoneStopwatch(duration => this.telemetryService.publicLog('searchResultsFinished', { duration }));
const progressEmitter = new Emitter<void>();
......
......@@ -9,7 +9,6 @@ import * as sinon from 'sinon';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { DeferredPPromise } from 'vs/base/test/common/utils';
import { PPromise } from 'vs/base/common/winjs.base';
import { nullEvent } from 'vs/base/common/timer';
import { SearchModel } from 'vs/workbench/parts/search/common/searchModel';
import URI from 'vs/base/common/uri';
import { IFileMatch, ILineMatch, ISearchService, ISearchComplete, ISearchProgressItem, IUncachedSearchStats } from 'vs/platform/search/common/search';
......@@ -20,6 +19,27 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
const nullEvent = new class {
public id: number;
public topic: string;
public name: string;
public description: string;
public data: any;
public startTime: Date;
public stopTime: Date;
public stop(): void {
return;
}
public timeTaken(): number {
return -1;
}
};
suite('SearchModel', () => {
let instantiationService: TestInstantiationService;
......@@ -292,4 +312,4 @@ suite('SearchModel', () => {
return instantiationService.createInstance(ModelServiceImpl);
}
});
\ No newline at end of file
});
......@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as timer from 'vs/base/common/timer';
import { ITimerService, IStartupMetrics, IInitData, IMemoryInfo } from 'vs/workbench/services/timer/common/timerService';
import * as os from 'os';
......@@ -54,9 +53,6 @@ export class TimerService implements ITimerService {
this.isInitialStartup = initData.isInitialStartup;
this.hasAccessibilitySupport = initData.hasAccessibilitySupport;
// forward start time to time keeper
timer.TimeKeeper.PARSE_TIME = initData.isInitialStartup ? initData.start : initData.windowLoad;
}
public computeStartupMetrics(): void {
......
......@@ -22,7 +22,6 @@ import { SearchService } from 'vs/workbench/services/search/node/searchService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { TestEnvironmentService, TestEditorService, TestEditorGroupService } from 'vs/workbench/test/workbenchTestServices';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import * as Timer from 'vs/base/common/timer';
import { TPromise } from 'vs/base/common/winjs.base';
import URI from 'vs/base/common/uri';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
......@@ -31,6 +30,23 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { IModelService } from 'vs/editor/common/services/modelService';
namespace Timer {
export interface ITimerEvent {
id: number;
topic: string;
name: string;
description: string;
data: any;
startTime: Date;
stopTime: Date;
stop(stopTime?: Date): void;
timeTaken(): number;
}
}
declare var __dirname: string;
// Checkout sources to run against:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册