3
3
from __future__ import annotations
4
4
5
5
import asyncio
6
+ from collections import deque
6
7
from collections .abc import AsyncIterable , Iterable
7
8
from pathlib import Path
8
9
from typing import TYPE_CHECKING , TypedDict , cast , overload
12
13
from choreographer .errors import ChromeNotFoundError
13
14
from choreographer .utils import TmpDirectory
14
15
15
- from . import _fig_tools , _path_tools , _utils
16
+ from . import _fig_tools , _path_tools , _profiler , _utils
16
17
from ._kaleido_tab import _KaleidoTab
17
18
from ._page_generator import PageGenerator
18
19
@@ -155,6 +156,7 @@ def __init__(
155
156
self .tabs_ready = asyncio .Queue (maxsize = 0 )
156
157
self ._total_tabs = 0 # tabs properly registered
157
158
self ._html_tmp_dir = None
159
+ self ._task_profiler : deque [_profiler .WriteCall ] = deque (maxlen = 5 )
158
160
159
161
# Kaleido Config
160
162
page = page_generator
@@ -305,8 +307,10 @@ async def _render_task(
305
307
self ,
306
308
fig_arg : FigureDict ,
307
309
* ,
310
+ topojson : str | None ,
308
311
_write : bool ,
309
- ** kwargs : Any ,
312
+ profiler : _profiler .WriteCall ,
313
+ stepper : bool ,
310
314
) -> None | bytes :
311
315
spec = _fig_tools .coerce_for_js (
312
316
fig_arg .get ("fig" ),
@@ -324,25 +328,40 @@ async def _render_task(
324
328
325
329
tab = await self ._get_kaleido_tab ()
326
330
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
+
327
338
try :
328
339
img_bytes = await asyncio .wait_for (
329
340
tab ._calc_fig ( # noqa: SLF001
330
341
spec ,
331
- ** kwargs ,
342
+ topojson = topojson ,
343
+ render_prof = render_prof ,
344
+ stepper = stepper ,
332
345
),
333
346
self ._timeout ,
334
347
)
335
348
if _write :
349
+ render_prof .profile_log .tick ("starting file write" )
336
350
await _utils .to_thread (full_path .write_bytes , img_bytes )
351
+ render_prof .profile_log .tick ("file write done" )
337
352
return None
338
353
else :
339
354
return img_bytes
340
- except :
355
+ except BaseException as e :
356
+ render_prof .profile_log .tick ("errored out" )
341
357
if _write :
342
358
full_path .unlink () # failure, no write
359
+ render_prof .error = e
343
360
raise
344
361
finally :
362
+ render_prof .profile_log .tick ("returning tab" )
345
363
await self ._return_kaleido_tab (tab )
364
+ render_prof .profile_log .tick ("tab returned" )
346
365
347
366
### API ###
348
367
@overload
@@ -400,8 +419,13 @@ async def write_fig_from_object(
400
419
if _is_figuredict (fig_dicts ):
401
420
fig_dicts = [fig_dicts ]
402
421
422
+ name = "No Name"
403
423
if main_task := asyncio .current_task ():
404
424
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 )
405
429
406
430
tasks : set [asyncio .Task ] = set ()
407
431
@@ -412,6 +436,7 @@ async def write_fig_from_object(
412
436
fig_arg = fig_arg ,
413
437
topojson = fig_arg .get ("topojson" ),
414
438
_write = _write , # backwards compatibility
439
+ profiler = profiler ,
415
440
stepper = stepper ,
416
441
),
417
442
)
0 commit comments