33from __future__ import annotations
44
55import asyncio
6+ from collections import deque
67from collections .abc import AsyncIterable , Iterable
78from pathlib import Path
89from typing import TYPE_CHECKING , TypedDict , cast , overload
1213from choreographer .errors import ChromeNotFoundError
1314from choreographer .utils import TmpDirectory
1415
15- from . import _fig_tools , _path_tools , _utils
16+ from . import _fig_tools , _path_tools , _profiler , _utils
1617from ._kaleido_tab import _KaleidoTab
1718from ._page_generator import PageGenerator
1819
@@ -155,6 +156,7 @@ def __init__(
155156 self .tabs_ready = asyncio .Queue (maxsize = 0 )
156157 self ._total_tabs = 0 # tabs properly registered
157158 self ._html_tmp_dir = None
159+ self ._task_profiler : deque [_profiler .WriteCall ] = deque (maxlen = 5 )
158160
159161 # Kaleido Config
160162 page = page_generator
@@ -305,8 +307,10 @@ async def _render_task(
305307 self ,
306308 fig_arg : FigureDict ,
307309 * ,
310+ topojson : str | None ,
308311 _write : bool ,
309- ** kwargs : Any ,
312+ profiler : _profiler .WriteCall ,
313+ stepper : bool ,
310314 ) -> None | bytes :
311315 spec = _fig_tools .coerce_for_js (
312316 fig_arg .get ("fig" ),
@@ -324,25 +328,40 @@ async def _render_task(
324328
325329 tab = await self ._get_kaleido_tab ()
326330
331+ render_prof = _profiler .RenderTaskProfile (
332+ spec ,
333+ full_path if _write else None ,
334+ tab .tab .target_id ,
335+ )
336+ profiler .renders .append (render_prof )
337+
327338 try :
328339 img_bytes = await asyncio .wait_for (
329340 tab ._calc_fig ( # noqa: SLF001
330341 spec ,
331- ** kwargs ,
342+ topojson = topojson ,
343+ render_prof = render_prof ,
344+ stepper = stepper ,
332345 ),
333346 self ._timeout ,
334347 )
335348 if _write :
349+ render_prof .profile_log .tick ("starting file write" )
336350 await _utils .to_thread (full_path .write_bytes , img_bytes )
351+ render_prof .profile_log .tick ("file write done" )
337352 return None
338353 else :
339354 return img_bytes
340- except :
355+ except BaseException as e :
356+ render_prof .profile_log .tick ("errored out" )
341357 if _write :
342358 full_path .unlink () # failure, no write
359+ render_prof .error = e
343360 raise
344361 finally :
362+ render_prof .profile_log .tick ("returning tab" )
345363 await self ._return_kaleido_tab (tab )
364+ render_prof .profile_log .tick ("tab returned" )
346365
347366 ### API ###
348367 @overload
@@ -400,8 +419,13 @@ async def write_fig_from_object(
400419 if _is_figuredict (fig_dicts ):
401420 fig_dicts = [fig_dicts ]
402421
422+ name = "No Name"
403423 if main_task := asyncio .current_task ():
404424 self ._main_render_coroutines .add (main_task )
425+ name = main_task .get_name ()
426+
427+ profiler = _profiler .WriteCall (name )
428+ self ._task_profiler .append (profiler )
405429
406430 tasks : set [asyncio .Task ] = set ()
407431
@@ -412,6 +436,7 @@ async def write_fig_from_object(
412436 fig_arg = fig_arg ,
413437 topojson = fig_arg .get ("topojson" ),
414438 _write = _write , # backwards compatibility
439+ profiler = profiler ,
415440 stepper = stepper ,
416441 ),
417442 )
0 commit comments