From 20dc4446a4822ad1adddcc68340f9105b0bf670e Mon Sep 17 00:00:00 2001 From: Arild Matsson Date: Mon, 9 Dec 2024 14:59:10 +0100 Subject: [PATCH] perf: avoid repeating costly stringifier lookup for each stats row --- CHANGELOG.md | 1 + app/config/statistics_config.ts | 44 +++++++++++---------------------- app/scripts/statistics.ts | 5 ++-- 3 files changed, 18 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40fdf7dd..342ca959 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - Search history is stored as parameters only, not full urls #118 - Enabled the `noImplicitAny` TypeScript flag for added strictness, and fixed/refactored various parts as a consequence - The `hitCountHtml` util function now takes the numbers as a tuple +- `reduceStringify()` now returns the stringifier, so it can be called only once per attribute ### Fixed diff --git a/app/config/statistics_config.ts b/app/config/statistics_config.ts index bf50eab1..05c10d49 100644 --- a/app/config/statistics_config.ts +++ b/app/config/statistics_config.ts @@ -3,9 +3,7 @@ import _ from "lodash" import settings from "@/settings" import { lemgramToHtml, regescape, saldoToHtml } from "@/util" import { locAttribute } from "@/i18n" -import { Token } from "@/backend/kwic-proxy" import { Attribute } from "@/settings/config.types" -import { JQueryStaticExtended } from "@/jquery.types" type Stringifier = (tokens: string[], ignoreCase?: boolean) => string @@ -103,22 +101,19 @@ function reduceCqp(type: string, tokens: string[], ignoreCase: boolean): string } // Get the html (no linking) representation of the result for the statistics table -export function reduceStringify(type: string, values: string[], structAttr?: Attribute): string { +export function reduceStringify(type: string, structAttr?: Attribute): (values: string[]) => string { let attrs = settings.corpusListing.getCurrentAttributes() if (attrs[type] && attrs[type].stats_stringify) { - return customFunctions[attrs[type].stats_stringify!](values) + return customFunctions[attrs[type].stats_stringify!] } switch (type) { case "word": case "msd": - return values.join(" ") + return (values) => values.join(" ") case "pos": - var output = _.map(values, function (token) { - return locAttribute(attrs["pos"].translation, token) - }).join(" ") - return output + return (values) => values.map((token) => locAttribute(attrs["pos"].translation, token)).join(" ") case "saldo": case "prefix": case "suffix": @@ -134,42 +129,31 @@ export function reduceStringify(type: string, values: string[], structAttr?: Att stringify = lemgramToHtml } - const html = _.map(values, function (token) { - if (token === "") return "–" - return stringify(token.replace(/:.*/g, ""), true) - }) - - return html.join(" ") + return (values) => + values.map((token) => (token === "" ? "–" : stringify(token.replace(/:.*/g, ""), true))).join(" ") case "transformer-neighbour": - return values.map((value) => value.replace(/:.*/g, "")).join(" ") + return (values) => values.map((value) => value.replace(/:.*/g, "")).join(" ") case "deprel": - var output = _.map(values, function (token) { - return locAttribute(attrs["deprel"].translation, token) - }).join(" ") - return output + return (values) => values.map((token) => locAttribute(attrs["deprel"].translation, token)).join(" ") case "msd_orig": // TODO: OMG this is corpus specific, move out to config ASAP (ASU corpus) - var output = _.map(values, function (token) { - return ($("").text(token) as any).outerHTML() - }).join(" ") - return output + return (values) => values.map((token) => ($("").text(token) as any).outerHTML()).join(" ") default: if (attrs[type]) { // word attributes - return values.join(" ") + return (values) => values.join(" ") } else { // structural attributes - var mapped = _.map(values, function (value) { + function stringify(value: string) { if (value === "") { return "-" } else if (structAttr?.translation) { return locAttribute(structAttr.translation, value) - } else { - return value } - }) - return mapped.join(" ") + return value + } + return (values) => values.map(stringify).join(" ") } } } diff --git a/app/scripts/statistics.ts b/app/scripts/statistics.ts index 3f84ca81..e5a8a413 100644 --- a/app/scripts/statistics.ts +++ b/app/scripts/statistics.ts @@ -12,7 +12,7 @@ import { SearchParams, SlickgridColumn, } from "./statistics.types" -import { hitCountHtml } from "@/util" +import { fromKeys, hitCountHtml } from "@/util" import { LangString } from "./i18n/types" import { getLang, locObj } from "./i18n" const pieChartImg = require("../img/stats2.png") @@ -100,11 +100,12 @@ const createStatisticsService = function () { // Format the values of the attributes we are reducing by const cl = settings.corpusListing.subsetFactory(corpora) const structAttrs = cl.getStructAttrs() + const stringifiers = fromKeys(reduceVals, (attr) => reduceStringify(attr, structAttrs[attr])) for (const row of e.data) { if (isTotalRow(row)) continue for (const type of row.statsValues) { for (const attr in type) { - row.formattedValue[attr] = reduceStringify(attr, type[attr], structAttrs[attr]) + row.formattedValue[attr] = stringifiers[attr](type[attr]) } } }