Query Editor Memory improvements (#3041)

* working through memory issues

* work in progress

* add missing value

* work in progress

* more work in progress

* various more memory fixes

* additional improvements

* fix imports

* change test that we dispose queries on close not dispose

* update tests
This commit is contained in:
Anthony Dresser
2018-11-05 16:08:41 -08:00
committed by GitHub
parent 399d6d0045
commit 5f2e17a738
22 changed files with 280 additions and 129 deletions

View File

@@ -33,4 +33,8 @@ export class ChartTab implements IPanelTab {
public dispose() {
this.view.dispose();
}
public clear() {
this.view.clear();
}
}

View File

@@ -35,6 +35,10 @@ export class ChartState {
options: IInsightOptions = {
type: ChartType.Bar
};
dispose() {
}
}
declare class Proxy {
@@ -134,6 +138,15 @@ export class ChartView extends Disposable implements IPanelView {
this.buildOptions();
}
public clear() {
}
public dispose() {
dispose(this.optionDisposables);
super.dispose();
}
render(container: HTMLElement): void {
if (!this.container) {
this.container = $('div.chart-parent-container');

View File

@@ -7,7 +7,7 @@
import { attachTableStyler } from 'sql/common/theme/styler';
import QueryRunner from 'sql/parts/query/execution/queryRunner';
import { VirtualizedCollection, AsyncDataProvider } from 'sql/base/browser/ui/table/asyncDataView';
import { Table, ITableStyles, ITableMouseEvent } from 'sql/base/browser/ui/table/table';
import { Table } from 'sql/base/browser/ui/table/table';
import { ScrollableSplitView } from 'sql/base/browser/ui/scrollableSplitview/scrollableSplitview';
import { MouseWheelSupport } from 'sql/base/browser/ui/table/plugins/mousewheelTableScroll.plugin';
import { AutoColumnSize } from 'sql/base/browser/ui/table/plugins/autoSizeColumns.plugin';
@@ -19,6 +19,7 @@ import { escape } from 'sql/base/common/strings';
import { hyperLinkFormatter, textFormatter } from 'sql/parts/grid/services/sharedServices';
import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugin';
import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin';
import { ITableStyles, ITableMouseEvent } from 'sql/base/browser/ui/table/interfaces';
import * as sqlops from 'sqlops';
import * as pretty from 'pretty-data';
@@ -61,6 +62,10 @@ export class GridPanelState {
public tableStates: GridTableState[] = [];
public scrollPosition: number;
public collapsed = false;
dispose() {
dispose(this.tableStates);
}
}
export interface IGridTableState {
@@ -68,14 +73,14 @@ export interface IGridTableState {
maximized: boolean;
}
export class GridTableState {
export class GridTableState extends Disposable {
private _maximized: boolean;
private _onMaximizedChange = new Emitter<boolean>();
private _onMaximizedChange = this._register(new Emitter<boolean>());
public onMaximizedChange: Event<boolean> = this._onMaximizedChange.event;
private _onCanBeMaximizedChange = new Emitter<boolean>();
private _onCanBeMaximizedChange = this._register(new Emitter<boolean>());
public onCanBeMaximizedChange: Event<boolean> = this._onCanBeMaximizedChange.event;
private _canBeMaximized: boolean;
@@ -86,6 +91,7 @@ export class GridTableState {
public activeCell: Slick.Cell;
constructor(public readonly resultId: number, public readonly batchId: number) {
super();
}
public get canBeMaximized(): boolean {
@@ -217,13 +223,13 @@ export class GridPanel extends ViewletPanel {
}
let table = this.instantiationService.createInstance(GridTable, this.runner, set);
table.state = tableState;
tableState.onMaximizedChange(e => {
this.tableDisposable.push(tableState.onMaximizedChange(e => {
if (e) {
this.maximizeTable(table.id);
} else {
this.minimizeTables();
}
});
}));
this.tableDisposable.push(attachTableStyler(table, this.themeService));
tables.push(table);
@@ -238,11 +244,17 @@ export class GridPanel extends ViewletPanel {
this.tables = this.tables.concat(tables);
}
public clear() {
this.reset();
}
private reset() {
for (let i = this.splitView.length - 1; i >= 0; i--) {
this.splitView.removeView(i);
}
dispose(this.tables);
dispose(this.tableDisposable);
this.tableDisposable = [];
this.tables = [];
this.maximizedGrid = undefined;
@@ -293,6 +305,15 @@ export class GridPanel extends ViewletPanel {
public get state(): GridPanelState {
return this._state;
}
public dispose() {
dispose(this.queryRunnerDisposables);
dispose(this.tableDisposable);
dispose(this.tables);
this.tableDisposable = undefined;
this.tables = undefined;
super.dispose();
}
}
class GridTable<T> extends Disposable implements IView {
@@ -444,9 +465,9 @@ class GridTable<T> extends Disposable implements IView {
private setupState() {
// change actionbar on maximize change
this.state.onMaximizedChange(this.rebuildActionBar, this);
this._register(this.state.onMaximizedChange(this.rebuildActionBar, this));
this.state.onCanBeMaximizedChange(this.rebuildActionBar, this);
this._register(this.state.onCanBeMaximizedChange(this.rebuildActionBar, this));
if (this.state.scrollPosition) {
// most of the time this won't do anything
@@ -656,6 +677,8 @@ class GridTable<T> extends Disposable implements IView {
public dispose() {
$(this.container).destroy();
this.table.dispose();
this.actionBar.dispose();
super.dispose();
}
}

View File

@@ -7,6 +7,7 @@
import 'vs/css!./media/messagePanel';
import { IMessagesActionContext, SelectAllMessagesAction, CopyMessagesAction } from './actions';
import QueryRunner from 'sql/parts/query/execution/queryRunner';
import { QueryInput } from 'sql/parts/query/common/queryInput';
import { IResultMessage, ISelectionData } from 'sqlops';
@@ -28,8 +29,6 @@ import { $ } from 'vs/base/browser/builder';
import { isArray, isUndefinedOrNull } from 'vs/base/common/types';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditor } from 'vs/editor/common/editorCommon';
import { QueryInput } from 'sql/parts/query/common/queryInput';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
export interface IResultMessageIntern extends IResultMessage {
@@ -71,6 +70,10 @@ export class MessagePanelState {
this.collapsed = !messagesOpenedSettings;
}
}
dispose() {
}
}
export class MessagePanel extends ViewletPanel {
@@ -102,6 +105,7 @@ export class MessagePanel extends ViewletPanel {
renderer: this.renderer,
controller: this.controller
}, { keyboardSupport: false, horizontalScrollMode: ScrollbarVisibility.Auto });
this.disposables.push(this.tree);
this.tree.onDidScroll(e => {
if (this.state) {
this.state.scrollPosition = this.tree.getScrollPosition();
@@ -117,7 +121,7 @@ export class MessagePanel extends ViewletPanel {
protected renderBody(container: HTMLElement): void {
this.container.style.width = '100%';
this.container.style.height = '100%';
attachListStyler(this.tree, this.themeService);
this.disposables.push(attachListStyler(this.tree, this.themeService));
container.appendChild(this.container);
this.tree.setInput(this.model);
}
@@ -193,9 +197,19 @@ export class MessagePanel extends ViewletPanel {
}
this.setExpanded(!this.state.collapsed);
}
public get state(): MessagePanelState {
return this._state;
}
public clear() {
this.reset();
}
public dispose() {
dispose(this.queryRunnerDisposables);
super.dispose();
}
}
class MessageDataSource implements IDataSource {

View File

@@ -478,11 +478,11 @@ export class QueryEditor extends BaseEditor {
this.setTaskbarContent();
this._configurationService.onDidChangeConfiguration(e => {
this._toDispose.push(this._configurationService.onDidChangeConfiguration(e => {
if (e.affectedKeys.includes('workbench.enablePreviewFeatures')) {
this.setTaskbarContent();
}
});
}));
}
private setTaskbarContent(): void {

View File

@@ -90,7 +90,6 @@ export class QueryResultsEditor extends BaseEditor {
public static ID: string = 'workbench.editor.queryResultsEditor';
public static AngularSelectorString: string = 'slickgrid-container.slickgridContainer';
protected _rawOptions: BareResultsGridInfo;
protected _input: QueryResultsInput;
private resultsView: QueryResultsView;
private styleSheet = DOM.createStyleSheet();
@@ -104,17 +103,17 @@ export class QueryResultsEditor extends BaseEditor {
) {
super(QueryResultsEditor.ID, telemetryService, themeService);
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
this._configurationService.onDidChangeConfiguration(e => {
this._register(this._configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('resultsGrid')) {
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
this.applySettings();
}
});
}));
this.applySettings();
}
public get input(): QueryResultsInput {
return this._input;
return this._input as QueryResultsInput;
}
private applySettings() {
@@ -133,10 +132,16 @@ export class QueryResultsEditor extends BaseEditor {
this.styleSheet.remove();
parent.appendChild(this.styleSheet);
if (!this.resultsView) {
this.resultsView = new QueryResultsView(parent, this._instantiationService, this._queryModelService);
this.resultsView = this._register(new QueryResultsView(parent, this._instantiationService, this._queryModelService));
}
}
dispose() {
this.styleSheet.remove();
this.styleSheet = undefined;
super.dispose();
}
layout(dimension: DOM.Dimension): void {
this.resultsView.layout(dimension);
}
@@ -147,6 +152,11 @@ export class QueryResultsEditor extends BaseEditor {
return TPromise.wrap<void>(null);
}
clearInput() {
this.resultsView.clearInput();
super.clearInput();
}
public chart(dataId: { batchId: number, resultId: number }) {
this.resultsView.chartData(dataId);
}
@@ -154,11 +164,4 @@ export class QueryResultsEditor extends BaseEditor {
public showQueryPlan(xml: string) {
this.resultsView.showPlan(xml);
}
public dispose(): void {
super.dispose();
if (this.resultsView) {
this.resultsView.dispose();
}
}
}

View File

@@ -111,6 +111,15 @@ class ResultsView extends Disposable implements IPanelView {
}
}
dispose() {
super.dispose();
}
public clear() {
this.gridPanel.clear();
this.messagePanel.clear();
}
remove(): void {
this.container.remove();
}
@@ -151,6 +160,10 @@ class ResultsTab implements IPanelTab {
public dispose() {
dispose(this.view);
}
public clear() {
this.view.clear();
}
}
export class QueryResultsView extends Disposable {
@@ -221,8 +234,11 @@ export class QueryResultsView extends Disposable {
}
}
public dispose() {
this._panelView.dispose();
clearInput() {
this._input = undefined;
this.resultsTab.clear();
this.qpTab.clear();
this.chartTab.clear();
}
public get input(): QueryResultsInput {
@@ -264,4 +280,8 @@ export class QueryResultsView extends Disposable {
this._panelView.removeTab(this.qpTab.identifier);
}
}
public dispose() {
super.dispose();
}
}