Skip to content

Commit

Permalink
[APM]Improve performance of join_by_key (#175177)
Browse files Browse the repository at this point in the history
## Summary

Improve performance of join_by_key from O(n^2) to O(n).
closes #176073
Fix
https://discuss.elastic.co/t/kibana-terribly-slow-on-apm-traces/312664

---------

Co-authored-by: Cauê Marcondes <55978943+cauemarcondes@users.noreply.github.com>
  • Loading branch information
clyfish and cauemarcondes authored Mar 6, 2024
1 parent f93c2a4 commit b22518c
Showing 1 changed file with 14 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/

import { UnionToIntersection, ValuesType } from 'utility-types';
import { isEqual, pull, merge, castArray } from 'lodash';
import { merge, castArray } from 'lodash';
import stableStringify from 'json-stable-stringify';

/**
* Joins a list of records by a given key. Key can be any type of value, from
Expand Down Expand Up @@ -56,18 +57,22 @@ export function joinByKey(
merge({}, a, b)
) {
const keys = castArray(key);
// Create a map to quickly query the key of group.
const map = new Map();
return items.reduce<Array<Record<string, any>>>((prev, current) => {
let item = prev.find((prevItem) =>
keys.every((k) => isEqual(prevItem[k], current[k]))
);
// The key of the map is a stable JSON string of the values from given keys.
// We need stable JSON string to support plain object values.
const stableKey = stableStringify(keys.map((k) => current[k]));

if (!item) {
item = { ...current };
prev.push(item);
if (map.has(stableKey)) {
const item = map.get(stableKey);
// delete and set the key to put it last
map.delete(stableKey);
map.set(stableKey, mergeFn(item, current));
} else {
pull(prev, item).push(mergeFn(item, current));
map.set(stableKey, { ...current });
}

return prev;
return [...map.values()];
}, []);
}

0 comments on commit b22518c

Please sign in to comment.