Skip to content

JSON encoding engine instrumentation #3012

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ jobs:
name: Build html figures
command: |
. venv/bin/activate
pip install pandas statsmodels --quiet
pip install pandas statsmodels orjson --quiet
python test/percy/plotly-express.py
- run:
name: Run percy snapshots
Expand Down
6 changes: 6 additions & 0 deletions packages/python/plotly/plotly/basedatatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,12 @@ def update(self, dict1=None, overwrite=False, **kwargs):
BaseFigure._perform_update(self[k], v)
else:
self[k] = v

# # instrumentation
# from plotly.io._json import to_json_plotly
#
# to_json_plotly(self)

return self

def pop(self, key, *args):
Expand Down
6 changes: 6 additions & 0 deletions packages/python/plotly/plotly/express/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2092,6 +2092,12 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None):

configure_axes(args, constructor, fig, orders)
configure_animation_controls(args, constructor, fig)

# instrumentation
# from plotly.io._json import to_json_plotly
#
# to_json_plotly(fig)

return fig


Expand Down
73 changes: 72 additions & 1 deletion packages/python/plotly/plotly/io/_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,78 @@ def coerce_to_strict(const):
return const


def time_engine(engine, plotly_object):
import time
# time in seconds
t_total = 0
n_total = 0

# Call function for at least total of 2 seconds and at least 10 times
n_min = 10
t_min = 1

while t_total < t_min or n_total < n_min:
t0 = time.perf_counter()
_to_json_plotly(plotly_object, engine=engine)
t1 = time.perf_counter()
n_total += 1
t_total += (t1 - t0)

# return time in ms
return 1000 * t_total / n_total


def to_json_plotly(plotly_object, pretty=False, engine=None):
if engine is not None:
return _to_json_plotly(plotly_object, pretty=pretty , engine=engine)

# instrucment _to_json_plotly by running it with all 3 engines and comparing results
# before returnin

import timeit
from IPython import get_ipython
ipython = get_ipython()
orjson = get_module("orjson", should_load=True)
results = {}
timing = {}
result_str = None
for engine in ["json", "orjson"]:
if orjson is None and engine == "orjson":
continue

result_str = _to_json_plotly(plotly_object, pretty=pretty, engine=engine)
results[engine] = from_json_plotly(result_str, engine=engine)
timing[engine] = time_engine(engine, plotly_object)

# Check matches
if "orjson" in results:
if results["json"] != results["orjson"]:
raise ValueError(
"""
{json}

{orjson}""".format(
json=results["json"], orjson=results["orjson"]
)
)

# write timing
import uuid
import pickle
import os
uid = str(uuid.uuid4())
with open("json_timing.csv".format(engine), "at") as f:
f.write("{}, {}, {}, {}\n".format(
timing["json"], timing["orjson"], len(result_str), uid)
)
os.makedirs("json_object", exist_ok=True)
with open("json_object/{uid}.pkl".format(uid=uid), "wb") as f:
pickle.dump(plotly_object, f)

return result_str


def _to_json_plotly(plotly_object, pretty=False, engine=None):
"""
Convert a plotly/Dash object to a JSON string representation

Expand Down Expand Up @@ -466,7 +537,7 @@ def clean_to_json_compatible(obj, **kwargs):
elif obj.dtype.kind == "U":
return obj.tolist()
elif obj.dtype.kind == "O":
# Treat object array as a lists, continue processing
# Treat object array as plain list, allow recursive processing below
obj = obj.tolist()
elif isinstance(obj, np.datetime64):
return str(obj)
Expand Down
2 changes: 1 addition & 1 deletion packages/python/plotly/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ deps=
optional: matplotlib==2.2.3
optional: scikit-image==0.14.4
optional: kaleido
optional: orjson==3.4.6;python_version>"3.5"
orjson==3.4.6;python_version>"3.5"

; CORE ENVIRONMENTS
[testenv:py27-core]
Expand Down