From 76a44b29f5a3765bb6462fbe6e129718206d63c6 Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Fri, 13 Jan 2023 09:50:04 +0000 Subject: [PATCH] [FIX] web: improve performance in list views with date/datetime fields When rendering the list view, we evaluate the evalContext for each field so that we can give it infos such as readonly, required, invalid or empty. In doing so, date and datetime feels are serialized and added to the evalContext, but serializing dates can be slow, especially when not using the default English locale. Internally, luxon checks whether the locale is English which instantiates an Intl object which can be slow and this is compounded by the fact that the method is called hundreds of time in a single render. This commit caches serialized dates and datetimes in a WeakMap, as the luxon Date objects are immutable, this is safe, and because these objects are not recreated often, it also eliminates a lot of the calls to luxon's toFormat. In the quotation list view, this brings the render time from ~1100ms to ~270ms. While this is still slow and further work will be undertaken to make the evalContext lazy (so that only date/datetimes which are actually used are serialized), it is a good first step and brings the performance back to a level where the list view is reasonably usable. closes odoo/odoo#110103 X-original-commit: 64eeeef4d3d93a9b2753520e0067aa7996988d4c Signed-off-by: Aaron Bohy (aab) --- addons/web/static/src/core/l10n/dates.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/core/l10n/dates.js b/addons/web/static/src/core/l10n/dates.js index 24186ee373e..8a252e3c1ad 100644 --- a/addons/web/static/src/core/l10n/dates.js +++ b/addons/web/static/src/core/l10n/dates.js @@ -409,20 +409,31 @@ export function deserializeDateTime(value) { return DateTime.fromSQL(value, { zone: "utc", numberingSystem: "latn" }).setZone("default"); } +const dateCache = new WeakMap(); /** * Returns a serialized string representing the given date. * @param {DateTime} value DateTime object, its timezone does not matter * @returns {string} serialized date, ready to be sent to the server */ export function serializeDate(value) { - return value.toFormat(SERVER_DATE_FORMAT, { numberingSystem: "latn" }); + if (!dateCache.has(value)) { + dateCache.set(value, value.toFormat(SERVER_DATE_FORMAT, { numberingSystem: "latn" })); + } + return dateCache.get(value); } +const dateTimeCache = new WeakMap(); /** * Returns a serialized string representing the given datetime. * @param {DateTime} value DateTime object, its timezone does not matter * @returns {string} serialized datetime, ready to be sent to the server */ export function serializeDateTime(value) { - return value.setZone("utc").toFormat(SERVER_DATETIME_FORMAT, { numberingSystem: "latn" }); + if (!dateTimeCache.has(value)) { + dateTimeCache.set( + value, + value.setZone("utc").toFormat(SERVER_DATETIME_FORMAT, { numberingSystem: "latn" }) + ); + } + return dateTimeCache.get(value); }