Skip to content
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

Use faster implementation for merging #186

Merged
merged 16 commits into from
Oct 5, 2022
3 changes: 2 additions & 1 deletion lib/Onyx.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as Logger from './Logger';
import cache from './OnyxCache';
import createDeferredTask from './createDeferredTask';
import mergeWithCustomized from './mergeWithCustomized';
import { merge } from './fastMerge';

// Keeps track of the last connectionID that was used so we can keep incrementing it
let lastConnectionID = 0;
Expand Down Expand Up @@ -761,7 +762,7 @@ function applyMerge(key, data) {
if (_.isObject(data) || _.every(mergeValues, _.isObject)) {
// Object values are merged one after the other
return _.reduce(mergeValues, (modifiedData, mergeValue) => {
const newData = mergeWithCustomized({}, modifiedData, mergeValue);
const newData = Object.assign({}, merge(modifiedData, mergeValue));

// We will also delete any object keys that are undefined or null.
// Deleting keys is not supported by AsyncStorage so we do it this way.
Expand Down
3 changes: 2 additions & 1 deletion lib/OnyxCache.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import _ from 'underscore';
import mergeWithCustomized from './mergeWithCustomized';
import { merge } from './fastMerge';
luacmartins marked this conversation as resolved.
Show resolved Hide resolved

const isDefined = _.negate(_.isUndefined);

Expand Down Expand Up @@ -110,7 +111,7 @@ class OnyxCache {
* @param {Record<string, *>} data - a map of (cache) key - values
*/
merge(data) {
this.storageMap = mergeWithCustomized({}, this.storageMap, data);
this.storageMap = Object.assign({}, merge(this.storageMap, data));
luacmartins marked this conversation as resolved.
Show resolved Hide resolved

const storageKeys = this.getAllKeys();
const mergedKeys = _.keys(data);
Expand Down
40 changes: 40 additions & 0 deletions lib/fastMerge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Mostly copied from https://medium.com/@lubaka.a/how-to-remove-lodash-performance-improvement-b306669ad0e1
mountiny marked this conversation as resolved.
Show resolved Hide resolved

function isMergeableObject(val) {
luacmartins marked this conversation as resolved.
Show resolved Hide resolved
var nonNullObject = val && typeof val === 'object';
return nonNullObject &&
Object.prototype.toString.call(val) !== '[object RegExp]' &&
Object.prototype.toString.call(val) !== '[object Date]';
}

let key = "";
function mergeObject(target, source) {
var destination = {};
if (isMergeableObject(target)) {
const targetKeys = Object.keys(target);
for (let i = 0; i < targetKeys.length; ++i) {
key = targetKeys[i];
destination[key] = target[key];
}
}
const sourceKeys = Object.keys(source);
for (let i = 0; i < sourceKeys.length; ++i) {
const key = sourceKeys[i];
if (!isMergeableObject(source[key]) || !target[key]) {
destination[key] = source[key];
} else {
destination[key] = merge(target[key], source[key])
}
}

return destination;
}

export function merge(target, source) {
var array = Array.isArray(source);
if (array) {
return source;
} else {
return mergeObject(target, source);
}
}