Skip to content

Commit e77018a

Browse files
authored
Minimize GPU usage for interactive and notebook editor (#8268)
* Minimize usage of the GPU and fix the execution count spinner * Add news entries
1 parent 306f5dc commit e77018a

File tree

13 files changed

+43
-38
lines changed

13 files changed

+43
-38
lines changed

news/2 Fixes/8003.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Make a spinner appear during executing a cell.

news/2 Fixes/8039.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Minimize the GPU impact of the interactive window and the notebook editor.

src/client/datascience/interactive-common/interactiveBase.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
346346
@captureTelemetry(Telemetry.Interrupt)
347347
public async interruptKernel(): Promise<void> {
348348
if (this.notebook && !this.restartingKernel) {
349-
const status = this.statusProvider.set(localize.DataScience.interruptKernelStatus(), undefined, undefined, this);
349+
const status = this.statusProvider.set(localize.DataScience.interruptKernelStatus(), true, undefined, undefined, this);
350350

351351
const settings = this.configuration.getSettings();
352352
const interruptTimeout = settings.datascience.jupyterInterruptTimeout;
@@ -463,7 +463,7 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
463463
}
464464

465465
// Start a status item
466-
const status = this.setStatus(localize.DataScience.executingCode());
466+
const status = this.setStatus(localize.DataScience.executingCode(), false);
467467

468468
// Transmit this submission to all other listeners (in a live share session)
469469
if (!id) {
@@ -662,8 +662,8 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
662662
}
663663
}
664664

665-
protected setStatus = (message: string): Disposable => {
666-
const result = this.statusProvider.set(message, undefined, undefined, this);
665+
protected setStatus = (message: string, showInWebView: boolean): Disposable => {
666+
const result = this.statusProvider.set(message, showInWebView, undefined, undefined, this);
667667
this.potentiallyUnfinishedStatus.push(result);
668668
return result;
669669
}
@@ -733,7 +733,7 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
733733
private async startServerImpl(): Promise<void> {
734734
// Status depends upon if we're about to connect to existing server or not.
735735
const status = (await this.jupyterExecution.getServer(await this.getNotebookOptions())) ?
736-
this.setStatus(localize.DataScience.connectingToJupyter()) : this.setStatus(localize.DataScience.startingJupyter());
736+
this.setStatus(localize.DataScience.connectingToJupyter(), true) : this.setStatus(localize.DataScience.startingJupyter(), true);
737737

738738
// Check to see if we support ipykernel or not
739739
try {
@@ -899,7 +899,7 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
899899
this.finishOutstandingCells();
900900

901901
// Set our status
902-
const status = this.statusProvider.set(localize.DataScience.restartingKernelStatus(), undefined, undefined, this);
902+
const status = this.statusProvider.set(localize.DataScience.restartingKernelStatus(), true, undefined, undefined, this);
903903

904904
try {
905905
if (this.notebook) {
@@ -951,7 +951,7 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
951951
}
952952

953953
private async reloadWithNew(): Promise<void> {
954-
const status = this.setStatus(localize.DataScience.startingJupyter());
954+
const status = this.setStatus(localize.DataScience.startingJupyter(), true);
955955
try {
956956
// Not the same as reload, we need to actually wait for the server.
957957
await this.stopServer();

src/client/datascience/interactive-ipynb/nativeEditor.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -467,10 +467,10 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
467467
* @private
468468
* @memberof NativeEditor
469469
*/
470-
private async updateVersionInfoInNotebook(): Promise<void>{
470+
private async updateVersionInfoInNotebook(): Promise<void> {
471471
// Use the active interpreter
472472
const usableInterpreter = await this.jupyterExecution.getUsableJupyterPython();
473-
if (usableInterpreter && usableInterpreter.version && this.notebookJson.metadata && this.notebookJson.metadata.language_info){
473+
if (usableInterpreter && usableInterpreter.version && this.notebookJson.metadata && this.notebookJson.metadata.language_info) {
474474
this.notebookJson.metadata.language_info.version = `${usableInterpreter.version.major}.${usableInterpreter.version.minor}.${usableInterpreter.version.patch}`;
475475
}
476476
}
@@ -580,11 +580,11 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
580580
* @memberof NativeEditor
581581
*/
582582
private async getStoredContents(): Promise<string | undefined> {
583-
const data = this.globalStorage.get<{contents?: string; lastModifiedTimeMs?: number}>(this.getStorageKey());
583+
const data = this.globalStorage.get<{ contents?: string; lastModifiedTimeMs?: number }>(this.getStorageKey());
584584
// Check whether the file has been modified since the last time the contents were saved.
585-
if (data && data.lastModifiedTimeMs && !this.isUntitled && this.file.scheme === 'file'){
585+
if (data && data.lastModifiedTimeMs && !this.isUntitled && this.file.scheme === 'file') {
586586
const stat = await this.fileSystem.stat(this.file.fsPath);
587-
if (stat.mtime > data.lastModifiedTimeMs){
587+
if (stat.mtime > data.lastModifiedTimeMs) {
588588
return;
589589
}
590590
}
@@ -605,7 +605,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
605605
const key = this.getStorageKey();
606606
// Keep track of the time when this data was saved.
607607
// This way when we retrieve the data we can compare it against last modified date of the file.
608-
await this.globalStorage.update(key, {contents, lastModifiedTimeMs: Date.now()});
608+
await this.globalStorage.update(key, { contents, lastModifiedTimeMs: Date.now() });
609609
}
610610

611611
private async close(): Promise<void> {
@@ -757,7 +757,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
757757

758758
@captureTelemetry(Telemetry.ConvertToPythonFile, undefined, false)
759759
private async export(cells: ICell[]): Promise<void> {
760-
const status = this.setStatus(localize.DataScience.convertingToPythonFile());
760+
const status = this.setStatus(localize.DataScience.convertingToPythonFile(), false);
761761
// First generate a temporary notebook with these cells.
762762
let tempFile: TemporaryFile | undefined;
763763
try {

src/client/datascience/interactive-window/interactiveWindowCommandListener.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ export class InteractiveWindowCommandListener implements IDataScienceCommandList
351351

352352
private waitForStatus<T>(promise: () => Promise<T>, format: string, file?: string, canceled?: () => void, interactiveWindow?: IInteractiveBase): Promise<T> {
353353
const message = file ? format.format(file) : format;
354-
return this.statusProvider.waitWithStatus(promise, message, undefined, canceled, interactiveWindow);
354+
return this.statusProvider.waitWithStatus(promise, message, true, undefined, canceled, interactiveWindow);
355355
}
356356

357357
@captureTelemetry(Telemetry.ImportNotebook, { scope: 'command' }, false)

src/client/datascience/statusProvider.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ export class StatusProvider implements IStatusProvider {
5555

5656
constructor(@inject(IApplicationShell) private applicationShell: IApplicationShell) { }
5757

58-
public set(message: string, timeout?: number, cancel?: () => void, panel?: IInteractiveBase): Disposable {
58+
public set(message: string, showInWebView: boolean, timeout?: number, cancel?: () => void, panel?: IInteractiveBase): Disposable {
5959
// Start our progress
60-
this.incrementCount(panel);
60+
this.incrementCount(showInWebView, panel);
6161

6262
// Create a StatusItem that will return our promise
6363
const statusItem = new StatusItem(message, () => this.decrementCount(panel), timeout);
@@ -82,9 +82,9 @@ export class StatusProvider implements IStatusProvider {
8282
return statusItem;
8383
}
8484

85-
public async waitWithStatus<T>(promise: () => Promise<T>, message: string, timeout?: number, cancel?: () => void, panel?: IInteractiveBase): Promise<T> {
85+
public async waitWithStatus<T>(promise: () => Promise<T>, message: string, showInWebView: boolean, timeout?: number, cancel?: () => void, panel?: IInteractiveBase): Promise<T> {
8686
// Create a status item and wait for our promise to either finish or reject
87-
const status = this.set(message, timeout, cancel, panel);
87+
const status = this.set(message, showInWebView, timeout, cancel, panel);
8888
let result: T;
8989
try {
9090
result = await promise();
@@ -94,9 +94,9 @@ export class StatusProvider implements IStatusProvider {
9494
return result;
9595
}
9696

97-
private incrementCount = (panel?: IInteractiveBase) => {
97+
private incrementCount = (showInWebView: boolean, panel?: IInteractiveBase) => {
9898
if (this.statusCount === 0) {
99-
if (panel) {
99+
if (panel && showInWebView) {
100100
panel.startProgress();
101101
}
102102
}

src/client/datascience/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,10 +383,10 @@ export const IStatusProvider = Symbol('IStatusProvider');
383383
export interface IStatusProvider {
384384
// call this function to set the new status on the active
385385
// interactive window. Dispose of the returned object when done.
386-
set(message: string, timeout?: number, canceled?: () => void, interactivePanel?: IInteractiveBase): Disposable;
386+
set(message: string, showInWebView: boolean, timeout?: number, canceled?: () => void, interactivePanel?: IInteractiveBase): Disposable;
387387

388388
// call this function to wait for a promise while displaying status
389-
waitWithStatus<T>(promise: () => Promise<T>, message: string, timeout?: number, canceled?: () => void, interactivePanel?: IInteractiveBase): Promise<T>;
389+
waitWithStatus<T>(promise: () => Promise<T>, message: string, showInWebView: boolean, timeout?: number, canceled?: () => void, interactivePanel?: IInteractiveBase): Promise<T>;
390390
}
391391

392392
export interface IJupyterCommand {

src/datascience-ui/history-react/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@
254254
--vscode-titleBar-activeForeground: #333333;
255255
--vscode-titleBar-inactiveBackground: rgba(221, 221, 221, 0.6);
256256
--vscode-titleBar-inactiveForeground: rgba(51, 51, 51, 0.6);
257+
--code-comment-color: green;
257258
--vscode-widget-shadow: #a8a8a8; }
258259

259260
body {

src/datascience-ui/interactive-common/common.css

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -388,24 +388,25 @@ body, html {
388388
grid-column: 1;
389389
font-weight: bold;
390390
color: var(--code-comment-color);
391-
display:flex;
392-
width: 16px;
393-
height: 16px;
391+
display:block;
392+
width: 8px;
393+
height: 8px;
394+
white-space: nowrap;
395+
}
396+
397+
@keyframes execution-spin {
398+
from { transform: rotate(0); }
399+
to { transform: rotate(360deg); }
394400
}
401+
395402
.execution-count-busy-svg {
396-
animation-name: spin;
397-
animation-duration: 4000ms;
398-
animation-iteration-count: infinite;
399-
animation-timing-function: linear;
400-
transform-origin: 50% 50%;
401-
width: 16px;
402-
height: 16px;
403+
animation: execution-spin 4s linear infinite;
403404
}
404405

405406
.execution-count-busy-polyline {
406407
fill: none;
407408
stroke: var(--code-comment-color);
408-
stroke-width: 5;
409+
stroke-width: 1;
409410
}
410411

411412
@keyframes spin {

src/datascience-ui/interactive-common/executionCount.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class ExecutionCount extends React.Component<IExecutionCountProps> {
2020

2121
return this.props.isBusy ?
2222
(
23-
<div className='execution-count-busy-outer'>[<svg className='execution-count-busy-svg' viewBox='0 0 100 100'><polyline points='50,0, 50,50, 85,15, 50,50, 100,50, 50,50, 85,85, 50,50 50,100 50,50 15,85 50,50 0,50 50,50 15,15' className='execution-count-busy-polyline' /></svg>]</div>
23+
<div className='execution-count-busy-outer'>[<svg className='execution-count-busy-svg' viewBox='0 0 16 16'><polyline points='8,0, 8,8, 14,3, 8,8, 16,8, 8,8, 14,14, 8,8 8,16 8,8 3,14 8,8 0,8 8,8 3,3' className='execution-count-busy-polyline' /></svg>]</div>
2424
) :
2525
(
2626
<div className='execution-count'>{`[${this.props.count}]`}</div>

0 commit comments

Comments
 (0)