Skip to content

Commit

Permalink
WIP feat: progressively load the widgets while the kernel is executing
Browse files Browse the repository at this point in the history
This will connect to the kernel as soon as possible, and tries to create
widget during execution. This avoids having to get all the widgets after
execution, and is an alterative to;
voila-dashboards#766

Issues:
 * since the whole jupyter message handling is 'synchronous' it awaits
   at a top level and goes all the way down, get_model needs to be resolved
   without any new message coming from the kernel.
 * Despite making handle_comm_open not returning a promise, we still get
   a stalling of the whole message q.

Despite these issues, the loading time is significantly reduced, since
the page renders almost instantly when it succeeds (e.g. when no widgets
are missed).
  • Loading branch information
maartenbreddels committed Nov 19, 2020
1 parent 4d72fb2 commit 13fe75d
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
39 changes: 38 additions & 1 deletion js/src/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export class WidgetManager extends JupyterLabManager {
mimeTypes: [WIDGET_MIMETYPE],
createRenderer: options => new WidgetRenderer(options, this)
}, 1);
this.missed_models = {}
this._registerWidgets();
this.loader = requireLoader;
}
Expand Down Expand Up @@ -147,8 +148,16 @@ export class WidgetManager extends JupyterLabManager {
});
}

async handle_comm_open(comm, msg) {
// make handle_comm_open not return a promose to we don't stall the message handling ordering
super.handle_comm_open(comm, msg);
return 42;
}

async _build_models() {
console.log('Creating jupyter-widgets');
const comm_ids = await this._get_comm_info();
const t0 = Date.now();
const models = {};
/**
* For the classical notebook, iopub_msg_rate_limit=1000 (default)
Expand All @@ -157,7 +166,7 @@ export class WidgetManager extends JupyterLabManager {
*/
const maxMessagesInTransit = 100; // really save limit compared to ZMQ_SNDHWM
const maxMessagesPerSecond = 500; // lets be on the save side, in case the kernel sends more msg'es
const widgets_info = await Promise.all(batchRateMap(Object.keys(comm_ids), async (comm_id) => {
const widgets_info = await Promise.all(batchRateMap(Object.keys(this.missed_models), async (comm_id) => {
const comm = await this._create_comm(this.comm_target_name, comm_id);
return this._update_comm(comm);
}, {room: maxMessagesInTransit, rate: maxMessagesPerSecond}));
Expand All @@ -174,10 +183,38 @@ export class WidgetManager extends JupyterLabManager {
);
const model = await modelPromise;
models[model.model_id] = model;
const missed = this.missed_models[model.model_id];
if (missed) {
console.log('found', model.model_id);
missed.accept(model);
}
return modelPromise;
}));
console.log('Took', Date.now() - t0, 'msec to fetch all widgets');
await Promise.all(Object.keys(this._models).map(async (id) => {
models[id] = await this._models[id]
}));
return models;
}
async new_model(options, serialized_state) {
const model_id = options.model_id;
const model = await super.new_model(options, serialized_state)
const missed = this.missed_models[model_id];
if (missed) {
console.log('found', model_id);
missed.accept(model);
}
}
async get_model(model_id) {
return super.get_model(model_id).catch((reason) => {
console.error('catch', reason);
this._models[model_id] = new Promise((resolve, reject) => {
console.log('missed', model_id)
this.missed_models[model_id] = {resolve, reject};
});
return this._models[model_id];
});
}

async _update_comm(comm) {
return new Promise(function(resolve, reject) {
Expand Down
3 changes: 2 additions & 1 deletion share/jupyter/voila/templates/lab/index.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ var voila_heartbeat = function() {
"kernelId": "{{kernel_id}}"
}
</script>
{{ voila_setup(resources.base_url, resources.nbextensions) }}

{% set cell_count = nb.cells|length %}
{#
Voilà is using Jinja's Template.generate method to not render the whole template in one go.
Expand Down Expand Up @@ -95,5 +97,4 @@ var voila_heartbeat = function() {
{%- endblock body_footer -%}

{% block footer_js %}
{{ voila_setup(resources.base_url, resources.nbextensions) }}
{% endblock footer_js %}

0 comments on commit 13fe75d

Please sign in to comment.