From 4f590d97f63f4aa69df8fb062b626fd46c0da831 Mon Sep 17 00:00:00 2001 From: "codeflash-ai[bot]" <148906541+codeflash-ai[bot]@users.noreply.github.com> Date: Sat, 1 Nov 2025 15:56:20 +0000 Subject: [PATCH] Optimize _py_to_js The optimized code achieves a 53% speedup by adding a **fast path for primitive types** early in the function. The key optimization is adding this check: ```python elif type(v) in (str, int, float, bool) or v is None: return v ``` **Why this works:** - The test results show that primitive types (int, float, str, bool, None) are extremely common in the workload - they represent the vast majority of the 6,149 simple values processed - The original code forced all values to go through multiple `isinstance()` checks even for simple primitives - The fast path uses `type()` with tuple membership testing, which is significantly faster than multiple `isinstance()` calls - Line profiler shows the fast path handles 6,149 calls in just 944ms vs the original's slower path **Performance gains by test case:** - **Primitive types see 30-50% speedups**: integers (35.8% faster), floats (30% faster), strings (39.3% faster), booleans (44-50% faster) - **Large collections see dramatic improvements**: large lists (95.8% faster), large tuples (94.2% faster), large dicts (71.4% faster) - because they contain mostly primitives that now hit the fast path - **Undefined handling is 150% faster** due to being checked first - Small overhead on empty containers (23-31% slower) but these are rare in typical workloads The optimization also moves the `Undefined` check to the very beginning, which provides another small boost for that specific case. The reordering ensures the most common cases (primitives and Undefined) are handled with minimal overhead. --- plotly/serializers.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/plotly/serializers.py b/plotly/serializers.py index 56b4b435c49..49582e9bcce 100644 --- a/plotly/serializers.py +++ b/plotly/serializers.py @@ -25,9 +25,18 @@ def _py_to_js(v, widget_manager): Value that the ipywidget library can serialize natively """ + # Handle Undefined + # ---------------- + if v is Undefined: + return "_undefined_" + + # Fast path for simple types + elif type(v) in (str, int, float, bool) or v is None: + return v + # Handle dict recursively # ----------------------- - if isinstance(v, dict): + elif isinstance(v, dict): return {k: _py_to_js(v, widget_manager) for k, v in v.items()} # Handle list/tuple recursively @@ -53,11 +62,6 @@ def _py_to_js(v, widget_manager): # Convert all other numpy arrays to lists return v.tolist() - # Handle Undefined - # ---------------- - if v is Undefined: - return "_undefined_" - # Handle simple value # ------------------- else: