Skip to content

Commit

Permalink
Add an option to show the cell outputs per second (#116)
Browse files Browse the repository at this point in the history
Co-authored-by: krassowski <5832902+krassowski@users.noreply.github.com>
  • Loading branch information
flaviomartins and krassowski committed Apr 26, 2024
1 parent 9c56a05 commit 7ebb8dc
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 4 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
@@ -1,3 +1,9 @@
## [3.2.0](https://github.com/deshaw/jupyterlab-execute-time/compare/v3.1.2...v3.2.0) (unreleased)

### Added

- Add an option to show the cell outputs per second [#116](https://github.com/deshaw/jupyterlab-execute-time/pull/116)

## [3.1.2](https://github.com/deshaw/jupyterlab-execute-time/compare/v3.1.0...v3.1.2) (2024-02-14)

### Fixed
Expand Down
6 changes: 6 additions & 0 deletions schema/settings.json
Expand Up @@ -59,6 +59,12 @@
"description": "Show the formatted date string in the given format. For example \"yyy-MM-dd HH:mm:ss\" results in \"2023-02-28 14:25:57 \", \"dd/MM/YYY HH:mm:ss (O)\" results in \"28/02/2023 14:25:57 (GMT +3)\". Find out more on unicode date field symbols on this link [https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table]",
"default": "yyy-MM-dd HH:mm:ss",
"pattern": "[yGuqQMLwdeEcabBhHkKmsSzOxX\\W].*"
},
"showOutputsPerSecond": {
"type": "boolean",
"title": "Show Outputs Per Second",
"description": "After a cell has finished running, show the outputs per second calculated from the last cell execution time and number of outputs.",
"default": false
}
}
}
24 changes: 20 additions & 4 deletions src/ExecuteTimeWidget.ts
Expand Up @@ -32,6 +32,7 @@ export interface IExecuteTimeSettings {
showDate: boolean;
historyCount: number;
dateFormat: string;
showOutputsPerSecond: boolean;
}

export default class ExecuteTimeWidget extends Widget {
Expand Down Expand Up @@ -290,11 +291,13 @@ export default class ExecuteTimeWidget extends Widget {
if (isLikelyAborted) {
msg = '';
} else if (endTime) {
if (
this._settings.minTime <=
differenceInMilliseconds(endTime, startTime) / 1000.0
) {
const executionTimeMillis = differenceInMilliseconds(
endTime,
startTime
);
if (this._settings.minTime <= executionTimeMillis / 1000.0) {
const executionTime = getTimeDiff(endTime, startTime);
const executionsPerSecond = 1000.0 / executionTimeMillis;
const lastExecutionTime = executionTimeNode.getAttribute(
PREV_DATA_EXECUTION_TIME_ATTR
);
Expand Down Expand Up @@ -324,6 +327,15 @@ export default class ExecuteTimeWidget extends Widget {
msg += ` at ${getTimeString(endTime, this._settings.dateFormat)}`;
}
msg += ` in ${executionTime}`;

const numberOfOutputs = cell.model.outputs.length;
if (this._settings.showOutputsPerSecond && numberOfOutputs > 0) {
const outputsPerSecond = executionsPerSecond / numberOfOutputs;
msg += `, ${numberOfOutputs} output${
numberOfOutputs === 1 ? '' : 's'
}`;
msg += ` at ${outputsPerSecond.toFixed(2)}/s`;
}
}
} else if (startTime) {
if (this._settings.showLiveExecutionTime) {
Expand Down Expand Up @@ -429,6 +441,9 @@ export default class ExecuteTimeWidget extends Widget {
);
}

this._settings.showOutputsPerSecond = settings.get('showOutputsPerSecond')
.composite as boolean;

const cells = this._panel.context.model.cells;
if (this._settings.enabled) {
cells.changed.connect(this.updateConnectedCell);
Expand Down Expand Up @@ -513,5 +528,6 @@ export default class ExecuteTimeWidget extends Widget {
showDate: true,
historyCount: 5,
dateFormat: 'yyy-MM-dd HH:mm:ss',
showOutputsPerSecond: false,
};
}
55 changes: 55 additions & 0 deletions ui-tests/notebooks/Timing_outputs_outcomes.ipynb
@@ -0,0 +1,55 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "98ce2d4e-e422-40ea-aa89-5adabbb8d0f0",
"metadata": {},
"source": [
"Notes:\n",
"- Each cells is self-contained to allow parallel testing.\n",
"- Cell indices are used in tests."
]
},
{
"cell_type": "markdown",
"id": "f28cb5ea-94a4-47d3-9860-4cf20a29d690",
"metadata": {},
"source": [
"#### Last executed at with outputs:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3cfa2867-8f80-4793-9a4d-d773b06136e1",
"metadata": {},
"outputs": [],
"source": [
"for i in range(5):\n",
" display(1)\n",
" sleep(0.01)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
34 changes: 34 additions & 0 deletions ui-tests/tests/timing_outputs_outcomes.spec.ts
@@ -0,0 +1,34 @@
import { expect, galata, test } from '@jupyterlab/galata';
import { openNotebook, cleanup, maskedScreenshot } from './utils';

const SETTINGS_ID = 'jupyterlab-execute-time:settings';

test.describe('Timing outcomes with ', () => {
test.beforeEach(openNotebook('Timing_outputs_outcomes.ipynb'));
test.afterEach(cleanup);
// Disable flashing highlight for screenshot consistency
test.use({
mockSettings: {
...galata.DEFAULT_SETTINGS,
[SETTINGS_ID]: {
...galata.DEFAULT_SETTINGS[SETTINGS_ID],
highlight: false,
showOutputsPerSecond: true,
},
},
});

test('"Last executed at" state', async ({ page }) => {
const cell = await page.notebook.getCell(2);

// Execute cell and wait for it to complete
await page.notebook.runCell(2);

const widget = await cell.waitForSelector('.execute-time');
expect(await widget.textContent()).toContain('Last executed at');
expect(await widget.textContent()).toContain('outputs at');
expect(await maskedScreenshot(widget)).toMatchSnapshot(
'last-executed-outputs.png'
);
});
});
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 7ebb8dc

Please sign in to comment.