Skip to content

Commit

Permalink
perf: remove lodash deps for smaller memory footprint
Browse files Browse the repository at this point in the history
  • Loading branch information
luin committed Oct 9, 2018
1 parent c091f2e commit 80f4a45
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 65 deletions.
3 changes: 2 additions & 1 deletion lib/cluster/ClusterSubscriber.ts
@@ -1,7 +1,8 @@
import {EventEmitter} from 'events'
import ConnectionPool from './ConnectionPool'
import {sample, noop} from '../utils/lodash'
import {noop} from '../utils/lodash'
import {getNodeKey} from './util'
import {sample} from '../utils'

const Redis = require('../redis')
const debug = require('../utils/debug')('ioredis:cluster:subscriber')
Expand Down
5 changes: 3 additions & 2 deletions lib/cluster/ConnectionPool.ts
@@ -1,6 +1,6 @@
import {parseURL} from '../utils'
import {EventEmitter} from 'events'
import {noop, defaults, values} from '../utils/lodash'
import {noop, defaults} from '../utils/lodash'
import {IRedisOptions, getNodeKey} from './util'

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

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

/**
Expand Down
8 changes: 4 additions & 4 deletions lib/cluster/index.js
Expand Up @@ -348,7 +348,7 @@ Cluster.prototype.refreshSlotsCache = function (callback) {
}
};

var keys = _.shuffle(Object.keys(this.connectionPool.nodes.all));
var keys = utils.shuffle(Object.keys(this.connectionPool.nodes.all));

var lastNodeError = null;

Expand Down Expand Up @@ -426,7 +426,7 @@ Cluster.prototype.sendCommand = function (command, stream, node) {
command.__is_reject_overwritten = true;
var reject = command.reject;
command.reject = function (err) {
var partialTry = _.partial(tryConnection, true);
var partialTry = tryConnection.bind(null, true)
_this.handleError(err, ttl, {
moved: function (slot, key) {
debug('command %s is moved to %s', command.name, key);
Expand Down Expand Up @@ -511,8 +511,8 @@ Cluster.prototype.sendCommand = function (command, stream, node) {
}
}
if (!redis) {
redis = _.sample(_this.connectionPool.nodes[to]) ||
_.sample(_this.connectionPool.nodes.all);
redis = utils.sample(_this.connectionPool.getNodes(to)) ||
utils.sample(_this.connectionPool.getNodes('all'));
}
}
if (node && !node.redis) {
Expand Down
6 changes: 4 additions & 2 deletions lib/commander.js
Expand Up @@ -26,7 +26,9 @@ function Commander() {
this.scriptsSet = {};
}

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

/**
Expand All @@ -53,7 +55,7 @@ Commander.prototype.createBuiltinCommand = function (commandName) {
};
};

_.forEach(commands, function (commandName) {
commands.forEach(function (commandName) {
Commander.prototype[commandName] = generateFunction(commandName, 'utf8');
Commander.prototype[commandName + 'Buffer'] = generateFunction(commandName, null);
});
Expand Down
3 changes: 1 addition & 2 deletions lib/connectors/SentinelConnector/index.ts
@@ -1,6 +1,5 @@
import {createConnection, Socket} from 'net'
import {sample} from '../../utils/lodash'
import {CONNECTION_CLOSED_ERROR_MSG, packObject} from '../../utils'
import {CONNECTION_CLOSED_ERROR_MSG, packObject, sample} from '../../utils'
import {TLSSocket} from 'tls'
import {ITcpConnectionOptions, isIIpcConnectionOptions} from '../StandaloneConnector'
import SentinelIterator from './SentinelIterator'
Expand Down
2 changes: 1 addition & 1 deletion lib/pipeline.js
Expand Up @@ -217,7 +217,7 @@ Pipeline.prototype.exec = function (callback) {
this.nodeifiedPromise = true;
asCallback(this.promise, callback);
}
if (_.isEmpty(this._queue)) {
if (!this._queue.length) {
this.resolve([]);
}
var pipelineSlot, i;
Expand Down
2 changes: 1 addition & 1 deletion lib/redis/parser.js
Expand Up @@ -70,7 +70,7 @@ exports.returnError = function (err) {
};

var sharedBuffers = {};
_.forEach(['message', 'pmessage', 'subscribe', 'psubscribe', 'unsubscribe', 'punsubscribe'], function (str) {
['message', 'pmessage', 'subscribe', 'psubscribe', 'unsubscribe', 'punsubscribe'].forEach(function (str) {
sharedBuffers[str] = Buffer.from(str);
});
exports.returnReply = function (reply) {
Expand Down
27 changes: 27 additions & 0 deletions lib/utils/index.ts
Expand Up @@ -293,6 +293,33 @@ export function sample<T> (array: T[], from: number = 0): T {
}
return array[from + Math.floor(Math.random() * (length - from))]
}
/**
* Shuffle the array using the Fisher-Yates Shuffle.
* This method will mutate the original array.
*
* @export
* @template T
* @param {T[]} array
* @returns {T[]}
*/
export function shuffle<T> (array: T[]): T[] {
let counter = array.length

// While there are elements in the array
while (counter > 0) {
// Pick a random index
const index = Math.floor(Math.random() * counter)

// Decrease counter by 1
counter--

// And swap the last element with it
[array[counter], array[index]] = [array[index], array[counter]]
}

return array
}


/**
* Error message for connection being disconnected
Expand Down
8 changes: 0 additions & 8 deletions lib/utils/lodash.js
@@ -1,13 +1,5 @@
'use strict';

exports.forEach = require('lodash.foreach');
exports.pick = require('lodash.pick');
exports.defaults = require('lodash.defaults');
exports.noop = function () {};
exports.difference = require('lodash.difference');
exports.sample = require('lodash.sample');
exports.flatten = require('lodash.flatten');
exports.isEmpty = require('lodash.isempty');
exports.values = require('lodash.values');
exports.shuffle = require('lodash.shuffle');
exports.partial = require('lodash.partial');
38 changes: 2 additions & 36 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 0 additions & 8 deletions package.json
Expand Up @@ -33,15 +33,7 @@
"denque": "^1.1.0",
"flexbuffer": "0.0.6",
"lodash.defaults": "^4.2.0",
"lodash.difference": "^4.5.0",
"lodash.flatten": "^4.4.0",
"lodash.foreach": "^4.5.0",
"lodash.isempty": "^4.4.0",
"lodash.partial": "^4.2.1",
"lodash.pick": "^4.4.0",
"lodash.sample": "^4.2.1",
"lodash.shuffle": "^4.2.0",
"lodash.values": "^4.3.0",
"redis-commands": "^1.3.5",
"redis-errors": "^1.2.0",
"redis-parser": "^3.0.0",
Expand Down
49 changes: 49 additions & 0 deletions test/unit/utils.js
Expand Up @@ -167,4 +167,53 @@ describe('utils', function () {
Math.random.restore();
});
});

describe('.shuffle', function () {
function compareArray (arr1, arr2) {
if (arr1.length !== arr2.length) {
return false
}
arr1.sort()
arr2.sort()
for (let i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i]) {
return false
}
}
return true
}
function testShuffle (arr) {
const origin = arr.slice(0)
expect(compareArray(origin, utils.shuffle(arr))).to.eql(true)
}
it('contains all items', () => {
testShuffle([1])
testShuffle([1, 2])
testShuffle([2, 1])
testShuffle([1, 1, 1])
testShuffle([1, 2, 3])
testShuffle([3, -1, 0, 2, -1])
testShuffle(['a', 'b', 'd', 'c'])
testShuffle(['c', 'b'])
})

it('mutates the original array', () => {
const arr = [3, 7]
const ret = utils.shuffle(arr)
expect(arr === ret).to.eql(true)
})

it('shuffles the array', () => {
const arr = [1, 2, 3, 4]
const copy = arr.slice(0)
while (true) {
utils.shuffle(copy)
for (let i = 0; i < copy.length; i++) {
if (arr[i] !== copy[i]) {
return
}
}
}
})
})
});

0 comments on commit 80f4a45

Please sign in to comment.