diff --git a/asv_bench/benchmarks/io/json.py b/asv_bench/benchmarks/io/json.py index bb09fe0ff634d..39f234c6fa816 100644 --- a/asv_bench/benchmarks/io/json.py +++ b/asv_bench/benchmarks/io/json.py @@ -294,7 +294,8 @@ def time_float_longint_str_lines(self): class ToJSONMem: def setup_cache(self): df = DataFrame([[1]]) - frames = {"int": df, "float": df.astype(float)} + df2 = DataFrame(range(8), date_range("1/1/2000", periods=8, freq="T")) + frames = {"int": df, "float": df.astype(float), "datetime": df2} return frames @@ -308,5 +309,10 @@ def peakmem_float(self, frames): for _ in range(100_000): df.to_json() + def peakmem_time(self, frames): + df = frames["datetime"] + for _ in range(10_000): + df.to_json(orient="table") + from ..pandas_vb_common import setup # noqa: F401 isort:skip diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index abe5a4840d57f..ca50bf46efd22 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -870,6 +870,7 @@ Performance improvements - Performance improvement in :func:`read_csv` when passing :func:`to_datetime` lambda-function to ``date_parser`` and inputs have mixed timezone offsetes (:issue:`35296`) - Performance improvement in :meth:`.SeriesGroupBy.value_counts` with categorical dtype (:issue:`46202`) - Fixed a reference leak in :func:`read_hdf` (:issue:`37441`) +- Fixed a memory leak in :meth:`DataFrame.to_json` and :meth:`Series.to_json` when serializing datetimes and timedeltas (:issue:`40443`) .. --------------------------------------------------------------------------- .. _whatsnew_200.bug_fixes: diff --git a/pandas/_libs/src/ujson/python/objToJSON.c b/pandas/_libs/src/ujson/python/objToJSON.c index a6f18e0aec4d9..13b96f9f8fccd 100644 --- a/pandas/_libs/src/ujson/python/objToJSON.c +++ b/pandas/_libs/src/ujson/python/objToJSON.c @@ -350,13 +350,15 @@ static char *PyUnicodeToUTF8(JSOBJ _obj, JSONTypeContext *tc, static char *NpyDateTimeToIsoCallback(JSOBJ Py_UNUSED(unused), JSONTypeContext *tc, size_t *len) { NPY_DATETIMEUNIT base = ((PyObjectEncoder *)tc->encoder)->datetimeUnit; - return int64ToIso(GET_TC(tc)->longValue, base, len); + GET_TC(tc)->cStr = int64ToIso(GET_TC(tc)->longValue, base, len); + return GET_TC(tc)->cStr; } /* JSON callback. returns a char* and mutates the pointer to *len */ static char *NpyTimeDeltaToIsoCallback(JSOBJ Py_UNUSED(unused), JSONTypeContext *tc, size_t *len) { - return int64ToIsoDuration(GET_TC(tc)->longValue, len); + GET_TC(tc)->cStr = int64ToIsoDuration(GET_TC(tc)->longValue, len); + return GET_TC(tc)->cStr; } /* JSON callback */