Skip to content

Commit 80f4a45

Browse files
committed
perf: remove lodash deps for smaller memory footprint
1 parent c091f2e commit 80f4a45

File tree

12 files changed

+94
-65
lines changed

12 files changed

+94
-65
lines changed

lib/cluster/ClusterSubscriber.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import {EventEmitter} from 'events'
22
import ConnectionPool from './ConnectionPool'
3-
import {sample, noop} from '../utils/lodash'
3+
import {noop} from '../utils/lodash'
44
import {getNodeKey} from './util'
5+
import {sample} from '../utils'
56

67
const Redis = require('../redis')
78
const debug = require('../utils/debug')('ioredis:cluster:subscriber')

lib/cluster/ConnectionPool.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {parseURL} from '../utils'
22
import {EventEmitter} from 'events'
3-
import {noop, defaults, values} from '../utils/lodash'
3+
import {noop, defaults} from '../utils/lodash'
44
import {IRedisOptions, getNodeKey} from './util'
55

66
const Redis = require('../redis')
@@ -23,7 +23,8 @@ export default class ConnectionPool extends EventEmitter {
2323
}
2424

2525
public getNodes(role: 'all' | 'master' | 'slave' = 'all'): any[] {
26-
return values(this.nodes[role])
26+
const nodes = this.nodes[role]
27+
return Object.keys(nodes).map((key) => nodes[key])
2728
}
2829

2930
/**

lib/cluster/index.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ Cluster.prototype.refreshSlotsCache = function (callback) {
348348
}
349349
};
350350

351-
var keys = _.shuffle(Object.keys(this.connectionPool.nodes.all));
351+
var keys = utils.shuffle(Object.keys(this.connectionPool.nodes.all));
352352

353353
var lastNodeError = null;
354354

@@ -426,7 +426,7 @@ Cluster.prototype.sendCommand = function (command, stream, node) {
426426
command.__is_reject_overwritten = true;
427427
var reject = command.reject;
428428
command.reject = function (err) {
429-
var partialTry = _.partial(tryConnection, true);
429+
var partialTry = tryConnection.bind(null, true)
430430
_this.handleError(err, ttl, {
431431
moved: function (slot, key) {
432432
debug('command %s is moved to %s', command.name, key);
@@ -511,8 +511,8 @@ Cluster.prototype.sendCommand = function (command, stream, node) {
511511
}
512512
}
513513
if (!redis) {
514-
redis = _.sample(_this.connectionPool.nodes[to]) ||
515-
_.sample(_this.connectionPool.nodes.all);
514+
redis = utils.sample(_this.connectionPool.getNodes(to)) ||
515+
utils.sample(_this.connectionPool.getNodes('all'));
516516
}
517517
}
518518
if (node && !node.redis) {

lib/commander.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ function Commander() {
2626
this.scriptsSet = {};
2727
}
2828

29-
var commands = _.difference(require('redis-commands').list, ['monitor']);
29+
var commands = require('redis-commands').list.filter(function (command) {
30+
return command !== 'monitor'
31+
})
3032
commands.push('sentinel');
3133

3234
/**
@@ -53,7 +55,7 @@ Commander.prototype.createBuiltinCommand = function (commandName) {
5355
};
5456
};
5557

56-
_.forEach(commands, function (commandName) {
58+
commands.forEach(function (commandName) {
5759
Commander.prototype[commandName] = generateFunction(commandName, 'utf8');
5860
Commander.prototype[commandName + 'Buffer'] = generateFunction(commandName, null);
5961
});

lib/connectors/SentinelConnector/index.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {createConnection, Socket} from 'net'
2-
import {sample} from '../../utils/lodash'
3-
import {CONNECTION_CLOSED_ERROR_MSG, packObject} from '../../utils'
2+
import {CONNECTION_CLOSED_ERROR_MSG, packObject, sample} from '../../utils'
43
import {TLSSocket} from 'tls'
54
import {ITcpConnectionOptions, isIIpcConnectionOptions} from '../StandaloneConnector'
65
import SentinelIterator from './SentinelIterator'

lib/pipeline.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ Pipeline.prototype.exec = function (callback) {
217217
this.nodeifiedPromise = true;
218218
asCallback(this.promise, callback);
219219
}
220-
if (_.isEmpty(this._queue)) {
220+
if (!this._queue.length) {
221221
this.resolve([]);
222222
}
223223
var pipelineSlot, i;

lib/redis/parser.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ exports.returnError = function (err) {
7070
};
7171

7272
var sharedBuffers = {};
73-
_.forEach(['message', 'pmessage', 'subscribe', 'psubscribe', 'unsubscribe', 'punsubscribe'], function (str) {
73+
['message', 'pmessage', 'subscribe', 'psubscribe', 'unsubscribe', 'punsubscribe'].forEach(function (str) {
7474
sharedBuffers[str] = Buffer.from(str);
7575
});
7676
exports.returnReply = function (reply) {

lib/utils/index.ts

+27
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,33 @@ export function sample<T> (array: T[], from: number = 0): T {
293293
}
294294
return array[from + Math.floor(Math.random() * (length - from))]
295295
}
296+
/**
297+
* Shuffle the array using the Fisher-Yates Shuffle.
298+
* This method will mutate the original array.
299+
*
300+
* @export
301+
* @template T
302+
* @param {T[]} array
303+
* @returns {T[]}
304+
*/
305+
export function shuffle<T> (array: T[]): T[] {
306+
let counter = array.length
307+
308+
// While there are elements in the array
309+
while (counter > 0) {
310+
// Pick a random index
311+
const index = Math.floor(Math.random() * counter)
312+
313+
// Decrease counter by 1
314+
counter--
315+
316+
// And swap the last element with it
317+
[array[counter], array[index]] = [array[index], array[counter]]
318+
}
319+
320+
return array
321+
}
322+
296323

297324
/**
298325
* Error message for connection being disconnected

lib/utils/lodash.js

-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
'use strict';
22

3-
exports.forEach = require('lodash.foreach');
4-
exports.pick = require('lodash.pick');
53
exports.defaults = require('lodash.defaults');
64
exports.noop = function () {};
7-
exports.difference = require('lodash.difference');
8-
exports.sample = require('lodash.sample');
95
exports.flatten = require('lodash.flatten');
10-
exports.isEmpty = require('lodash.isempty');
11-
exports.values = require('lodash.values');
12-
exports.shuffle = require('lodash.shuffle');
13-
exports.partial = require('lodash.partial');

package-lock.json

+2-36
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

-8
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,7 @@
3333
"denque": "^1.1.0",
3434
"flexbuffer": "0.0.6",
3535
"lodash.defaults": "^4.2.0",
36-
"lodash.difference": "^4.5.0",
3736
"lodash.flatten": "^4.4.0",
38-
"lodash.foreach": "^4.5.0",
39-
"lodash.isempty": "^4.4.0",
40-
"lodash.partial": "^4.2.1",
41-
"lodash.pick": "^4.4.0",
42-
"lodash.sample": "^4.2.1",
43-
"lodash.shuffle": "^4.2.0",
44-
"lodash.values": "^4.3.0",
4537
"redis-commands": "^1.3.5",
4638
"redis-errors": "^1.2.0",
4739
"redis-parser": "^3.0.0",

test/unit/utils.js

+49
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,53 @@ describe('utils', function () {
167167
Math.random.restore();
168168
});
169169
});
170+
171+
describe('.shuffle', function () {
172+
function compareArray (arr1, arr2) {
173+
if (arr1.length !== arr2.length) {
174+
return false
175+
}
176+
arr1.sort()
177+
arr2.sort()
178+
for (let i = 0; i < arr1.length; i++) {
179+
if (arr1[i] !== arr2[i]) {
180+
return false
181+
}
182+
}
183+
return true
184+
}
185+
function testShuffle (arr) {
186+
const origin = arr.slice(0)
187+
expect(compareArray(origin, utils.shuffle(arr))).to.eql(true)
188+
}
189+
it('contains all items', () => {
190+
testShuffle([1])
191+
testShuffle([1, 2])
192+
testShuffle([2, 1])
193+
testShuffle([1, 1, 1])
194+
testShuffle([1, 2, 3])
195+
testShuffle([3, -1, 0, 2, -1])
196+
testShuffle(['a', 'b', 'd', 'c'])
197+
testShuffle(['c', 'b'])
198+
})
199+
200+
it('mutates the original array', () => {
201+
const arr = [3, 7]
202+
const ret = utils.shuffle(arr)
203+
expect(arr === ret).to.eql(true)
204+
})
205+
206+
it('shuffles the array', () => {
207+
const arr = [1, 2, 3, 4]
208+
const copy = arr.slice(0)
209+
while (true) {
210+
utils.shuffle(copy)
211+
for (let i = 0; i < copy.length; i++) {
212+
if (arr[i] !== copy[i]) {
213+
return
214+
}
215+
}
216+
}
217+
})
218+
})
170219
});

0 commit comments

Comments
 (0)