From e87acf2a0505008d2d5cf68d85fd08d4184bbac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Piotr=20C=C5=82apa?= Date: Wed, 7 Apr 2021 14:31:42 +0200 Subject: [PATCH] Move the style overrides to a separate HTML widget Updating the styles every time we update the widget causes Safari to recalculate the styles and the layout for the whole notebook which completely ruins performance (100ms layouts on each update on an Apple M1). If we output the styles as a separate widget the browser only inteprets them once and layout times on updates stay < 10ms. --- fastprogress/_nbdev.py | 1 + fastprogress/core.py | 33 +++++---- fastprogress/fastprogress.py | 5 +- nbs/00_core.ipynb | 30 +++++---- nbs/01_fastprogress.ipynb | 125 ++++++++++++++++++++++++++++------- 5 files changed, 143 insertions(+), 51 deletions(-) diff --git a/fastprogress/_nbdev.py b/fastprogress/_nbdev.py index fc806f6..dd58d0c 100644 --- a/fastprogress/_nbdev.py +++ b/fastprogress/_nbdev.py @@ -4,6 +4,7 @@ index = {"format_time": "00_core.ipynb", "html_progress_bar": "00_core.ipynb", + "html_progress_bar_styles": "00_core.ipynb", "text2html_table": "00_core.ipynb", "in_colab": "00_core.ipynb", "IN_COLAB": "00_core.ipynb", diff --git a/fastprogress/core.py b/fastprogress/core.py index d27190b..27d3a00 100644 --- a/fastprogress/core.py +++ b/fastprogress/core.py @@ -1,6 +1,7 @@ # AUTOGENERATED! DO NOT EDIT! File to edit: nbs/00_core.ipynb (unless otherwise specified). -__all__ = ['format_time', 'html_progress_bar', 'text2html_table', 'in_colab', 'IN_COLAB', 'in_notebook', 'IN_NOTEBOOK'] +__all__ = ['format_time', 'html_progress_bar', 'html_progress_bar_styles', 'text2html_table', 'in_colab', 'IN_COLAB', + 'in_notebook', 'IN_NOTEBOOK'] # Cell def format_time(t): @@ -11,23 +12,29 @@ def format_time(t): else: return f'{m:02d}:{s:02d}' # Cell + +# the styles are static so we'll keep the browser from recalculating +# them every time we update the progress bar widget +html_progress_bar_styles = """ + +""" + def html_progress_bar(value, total, label, interrupted=False): "Html code for a progress bar `value`/`total` with `label`" bar_style = 'progress-bar-interrupted' if interrupted else '' return f"""
- {label}
diff --git a/fastprogress/fastprogress.py b/fastprogress/fastprogress.py index 177b327..b01f0a5 100644 --- a/fastprogress/fastprogress.py +++ b/fastprogress/fastprogress.py @@ -107,7 +107,9 @@ class NBProgressBar(ProgressBar): def on_iter_begin(self): super().on_iter_begin() self.progress = html_progress_bar(0, self.total, "") - if self.display: self.out = display(HTML(self.progress), display_id=True) + if self.display: + display(HTML(html_progress_bar_styles)) + self.out = display(HTML(self.progress), display_id=True) self.is_active=True def on_interrupt(self): @@ -138,6 +140,7 @@ def __init__(self, gen, total=None, hide_graph=False, order=None, clean_on_inter def on_iter_begin(self): self.html_code = '\n'.join([html_progress_bar(0, self.main_bar.total, ""), ""]) + display(HTML(html_progress_bar_styles)) self.out = display(HTML(self.html_code), display_id=True) def on_interrupt(self): diff --git a/nbs/00_core.ipynb b/nbs/00_core.ipynb index 6265deb..fa294d5 100644 --- a/nbs/00_core.ipynb +++ b/nbs/00_core.ipynb @@ -66,23 +66,29 @@ "outputs": [], "source": [ "# export\n", + "\n", + "# the styles are static so we'll keep the browser from recalculating\n", + "# them every time we update the progress bar widget\n", + "html_progress_bar_styles = \"\"\"\n", + "\n", + "\"\"\"\n", + "\n", "def html_progress_bar(value, total, label, interrupted=False):\n", " \"Html code for a progress bar `value`/`total` with `label`\"\n", " bar_style = 'progress-bar-interrupted' if interrupted else ''\n", " return f\"\"\"\n", "
\n", - " \n", " \n", " {label}\n", "
\n", diff --git a/nbs/01_fastprogress.ipynb b/nbs/01_fastprogress.ipynb index 3e4d8b0..4e6d48c 100644 --- a/nbs/01_fastprogress.ipynb +++ b/nbs/01_fastprogress.ipynb @@ -266,7 +266,9 @@ " def on_iter_begin(self):\n", " super().on_iter_begin()\n", " self.progress = html_progress_bar(0, self.total, \"\")\n", - " if self.display: self.out = display(HTML(self.progress), display_id=True)\n", + " if self.display:\n", + " display(HTML(html_progress_bar_styles))\n", + " self.out = display(HTML(self.progress), display_id=True)\n", " self.is_active=True\n", "\n", " def on_interrupt(self):\n", @@ -290,23 +292,35 @@ "execution_count": null, "metadata": {}, "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { "text/html": [ "\n", "
\n", - " \n", " \n", " 100.00% [100/100 00:05<00:00]\n", "
\n", @@ -330,23 +344,35 @@ "execution_count": null, "metadata": {}, "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { "text/html": [ "\n", "
\n", - " \n", " \n", " Interrupted\n", "
\n", @@ -397,6 +423,7 @@ " \n", " def on_iter_begin(self):\n", " self.html_code = '\\n'.join([html_progress_bar(0, self.main_bar.total, \"\"), \"\"])\n", + " display(HTML(html_progress_bar_styles))\n", " self.out = display(HTML(self.html_code), display_id=True)\n", "\n", " def on_interrupt(self):\n", @@ -463,6 +490,30 @@ "execution_count": null, "metadata": {}, "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { "text/html": [ @@ -490,6 +541,30 @@ "execution_count": null, "metadata": {}, "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "data": { "text/html": [