What are the performance differences between Promise.join Promise.all? - performance

I was combing through the Bluebird docs, and they recommend using Promise.join over Promise.all for concurrent discrete promises.
The documentation says
Promise.join is much easier (and more performant) to use when you have a fixed amount of discrete promises that you want to coordinate concurrently.
However there's no explanation about the performance comment.
The only difference I see is that .all does the extra operation of unpacking the array. Seems like a stretch to call that "more performant" so maybe there's something else under the hood?
Any explanation would be helpful, thanks!

I have not seen any major performance impacts. Checkout the Fiddle here for benchmarking this:
https://jsfiddle.net/msmta/3936tnca/
// spread
function startSpreadTest() {
var startTime = new Date()
var spreadArray = []
for(var i = 0; i < promiseCount; i++)
spreadArray.push(Promise.delay(promiseDelay))
return Promise.all(spreadArray).spread(function(){
return getStopTime(startTime)
})
}
// join
function startJoinTest() {
var startTime = new Date()
var args = []
for(var i = 0; i < promiseCount; i++)
args.push(Promise.delay(promiseDelay))
args.push(function(){
return getStopTime(startTime)
})
return Promise.join.apply(null, args)
}

Related

Differences between StringGetAsync vs StringGet in StackExchange.Redis Multiplexer Connection

I was wondering that there are any performance differences between
StringGetAsync vs StringGet while we are using the StackExchange.Redis Multiplexer Connection.
The StackExhange.Redis Document explained like
When used concurrently by different callers, it automatically pipelines the separate requests, so regardless of whether the requests use blocking or asynchronous access, the work is all pipelined.
The explanation is really confusing. Which one provides more performing code?
for (int i = 0; i < 5000; i++)
{
taskList.Add(Task.Run( async () =>
{
var value = db.StringGetAsync("Localization:ECommerceBackend:tr-TR:bo_IsThereAnyStoreStock");
}));
}
or
for (int i = 0; i < 5000; i++)
{
taskList.Add(Task.Run( async () =>
{
var value = db.StringGet("Localization:ECommerceBackend:tr-TR:bo_IsThereAnyStoreStock");
}));
}

How to get a loop to load movieclips with eventlisteners

I wanted the scene load 5 different movie clips (named B1-B5). Each movie clip is placed on a specific x and y. Each movie clip grows/shrinks on roll over/roll out....
I got the code working by typing everything out and duplicating each section per time but it's messy and I'd like to clean up the code by getting a loop to do it (if it's possible?).
This is the code that works but I'd have to duplicate it per movie clip (changing the obvious bits)...
var scene1:MovieClip = new B1();
addChild(scene1);
scene1.x = 170.30;
scene1.y = 231.15;
scene1.addEventListener(MouseEvent.MOUSE_OVER, onRollOverEvent1);
scene1.addEventListener(MouseEvent.MOUSE_OUT, onRollOutEvent1);
function onRollOverEvent1(e:MouseEvent) {
scene1.width=25.9;
scene1.height=25;
}
function onRollOutEvent1(e:MouseEvent) {
scene1.width = 20.9;
scene1.height = 20;
}
Below is what I've tried out but have been stuck for a good while...
for (var i:int=1; i<5; i++){
var scene[i]:MovieClip = new "B"+i();
addChild("scene"+i);
//var scene[i]:MovieClip = new B[i]();
scene[i].addEventListener(MouseEvent.MOUSE_OVER, onRollOverEvent);
scene[i].addEventListener(MouseEvent.MOUSE_OUT, onRollOutEvent)
function onRollOverEvent(e:MouseEvent) {
scene[i].width=25.9;
scene[i].height=25;
}
function onRollOutEvent(e:MouseEvent) {
scene[i].width = 20.9;
scene[i].height = 20;
}
}
scene1.x = 170.30;
scene1.y = 231.15;
scene2.x = 284.30;
scene2.y = 250.75;
scene3.x = 377.30;
scene3.y = 280.15;
scene4.x = 444.30;
scene4.y = 321.15;
scene5.x = 196.30;
scene5.y = 172.15;
First, lets go through your mistakes.
new "B"+i();
At the very best that translates to calling a number i as function and adding the result to "B" as a String. But even new "B1"() is not the same as new B1(). There is, in fact, a method getDefinitionByName(..) that allows to address a class via its name, but I don't recommend to use it because it is advanced topic.
var scene[i]:MovieClip
You just cannot define variables scene1, scene2, etc this way. The closest thing you can actually devise is the square bracket notation: this["scene" + i] = ....
addChild("scene"+i);
The argument must be a DisplayObject instance, not a String.
for (...)
{
...
function onRollOverEvent(e:MouseEvent)
...
}
Do not define functions inside other functions or loops.
scene[i].width = 20.9;
scene[i].height = 20;
By the end of your loop i will be equal to 5, so, what do you think such a record will address?
Then, the solution.
When you come to scaling your working solution to multiple instances, you are to go algorithmic. Loops and Arrays are your friends.
// Lets devise a list of classes and (x,y) coordinates.
var Designs:Array = [
null, // the 0-th element
{id:B1, x:170, y:230},
{id:B2, x:285, y:250},
];
for (var i:int = 1; i < Design.length; i++)
{
// Retrieve a record for the future object.
var aDesign:Object = Designs[i];
// Get a reference to the object's class.
var aClass:Class = aDesign.id;
// Create the object. Yes, you CAN omit () with
// the "new" operator if there are no mandatory arguments.
var aThing:Movieclip = new aClass;
// Set coordinates from the design record.
aThing.x = aDesign.x;
aThing.y = aDesign.y;
// Add to the display list.
addChild(aThing);
// Subscribe the event handlers.
aThing.addEventListener(MouseEvent.MOUSE_OVER, onOver);
aThing.addEventListener(MouseEvent.MOUSE_OUT, onOut);
// Save the object's reference for the later use.
// If you'd need to address, say, 3rd object,
// you do it as following:
// Designs[3].instance
aDesign.instance = aThing;
}
function onOver(e:MouseEvent):void
{
// You subscribed all of the objects to this one event handler.
// This is the correct way to learn, which one of the objects
// is under the mouse and is dispatching the said event.
var aThing:MovieClip = e.currentTarget as MovieClip;
// Change the object's size.
aThing.width = 26;
aThing.height = 25;
}
function onOut(e:MouseEvent):void
{
// Get the source of the dispatched event.
var aThing:MovieClip = e.currentTarget as MovieClip;
// Change the object's size.
aThing.width = 21;
aThing.height = 20;
}

node.js Number.prototype isn't behaving as expected

I'm trying to do a little math library to facilitate my app, this however is throwing an off error.
TypeError: Object 25 has no method 'permutation'
function permutate(p) {
var states = new Number(p.length)
chat( states.permutation(states) )
}
Number.prototype.factorial = function() {
for(var i = 2; i <= this; i++)
n*=i
return n
}
Number.prototype.permutation = function(r) {
return (this.factorial() / (this-r).factorial())
}
in addition to hopefully fixing my code, I'm really curious why the objects type is being interpreted as a number primitive? (or whatever is really going on here)

facing performance issues with knockout mapping plugin

I have decent large data set of around 1100 records. This data set is mapped to an observable array which is then bound to a view. Since these records are updated frequently, the observable array is updated every time using the ko.mapping.fromJS helper.
This particular command takes around 40s to process all the rows. The user interface just locks for that period of time.
Here is the code -
var transactionList = ko.mapping.fromJS([]);
//Getting the latest transactions which are around 1100 in number;
var data = storage.transactions();
//Mapping the data to the observable array, which takes around 40s
ko.mapping.fromJS(data,transactionList)
Is there a workaround for this? Or should I just opt of web workers to improve performances?
Knockout.viewmodel is a replacement for knockout.mapping that is significantly faster at creating viewmodels for large object arrays like this. You should notice a significant performance increase.
http://coderenaissance.github.com/knockout.viewmodel/
I have also thought of a workaround as follows, this uses less amount of code-
var transactionList = ko.mapping.fromJS([]);
//Getting the latest transactions which are around 1100 in number;
var data = storage.transactions();
//Mapping the data to the observable array, which takes around 40s
// Instead of - ko.mapping.fromJS(data,transactionList)
var i = 0;
//clear the list completely first
transactionList.destroyAll();
//Set an interval of 0 and keep pushing the content to the list one by one.
var interval = setInterval(function () {if (i == data.length - 1 ) {
clearInterval(interval);}
transactionList.push(ko.mapping.fromJS(data[i++]));
}, 0);
I had the same problem with mapping plugin. Knockout team says that mapping plugin is not intended to work with large arrays. If you have to load such big data to the page then likely you have improper design of the system.
The best way to fix this is to use server pagination instead of loading all the data on page load. If you don't want to change design of your application there are some workarounds which maybe help you:
Map your array manually:
var data = storage.transactions();
var mappedData = ko.utils.arrayMap(data , function(item){
return ko.mapping.fromJS(item);
});
var transactionList = ko.observableArray(mappedData);
Map array asynchronously. I have written a function that processes array by portions in another thread and reports progress to the user:
function processArrayAsync(array, itemFunc, afterStepFunc, finishFunc) {
var itemsPerStep = 20;
var processor = new function () {
var self = this;
self.array = array;
self.processedCount = 0;
self.itemFunc = itemFunc;
self.afterStepFunc = afterStepFunc;
self.finishFunc = finishFunc;
self.step = function () {
var tillCount = Math.min(self.processedCount + itemsPerStep, self.array.length);
for (; self.processedCount < tillCount; self.processedCount++) {
self.itemFunc(self.array[self.processedCount], self.processedCount);
}
self.afterStepFunc(self.processedCount);
if (self.processedCount < self.array.length - 1)
setTimeout(self.step, 1);
else
self.finishFunc();
};
};
processor.step();
};
Your code:
var data = storage.transactions();
var transactionList = ko.observableArray([]);
processArrayAsync(data,
function (item) { // Step function
var transaction = ko.mapping.fromJS(item);
transactionList().push(transaction);
},
function (processedCount) {
var percent = Math.ceil(processedCount * 100 / data.length);
// Show progress to the user.
ShowMessage(percent);
},
function () { // Final function
// This function will fire when all data are mapped. Do some work (i.e. Apply bindings).
});
Also you can try alternative mapping library: knockout.wrap. It should be faster than mapping plugin.
I have chosen the second option.
Mapping is not magic. In most of the cases this simple recursive function can be sufficient:
function MyMapJS(a_what, a_path)
{
a_path = a_path || [];
if (a_what != null && a_what.constructor == Object)
{
var result = {};
for (var key in a_what)
result[key] = MyMapJS(a_what[key], a_path.concat(key));
return result;
}
if (a_what != null && a_what.constructor == Array)
{
var result = ko.observableArray();
for (var index in a_what)
result.push(MyMapJS(a_what[index], a_path.concat(index)));
return result;
}
// Write your condition here:
switch (a_path[a_path.length-1])
{
case 'mapThisProperty':
case 'andAlsoThisOne':
result = ko.observable(a_what);
break;
default:
result = a_what;
break;
}
return result;
}
The code above makes observables from the mapThisProperty and andAlsoThisOne properties at any level of the object hierarchy; other properties are left constant. You can express more complex conditions using a_path.length for the level (depth) the value is at, or using more elements of a_path. For example:
if (a_path.length >= 2
&& a_path[a_path.length-1] == 'mapThisProperty'
&& a_path[a_path.length-2] == 'insideThisProperty')
result = ko.observable(a_what);
You can use typeOf a_what in the condition, e.g. to make all strings observable.
You can ignore some properties, and insert new ones at certain levels.
Or, you can even omit a_path. Etc.
The advantages are:
Customizable (more easily than knockout.mapping).
Short enough to copy-paste it and write individual mappings for different objects if needed.
Smaller code, knockout.mapping-latest.js is not included into your page.
Should be faster as it does only what is absolutely necessary.

jQuery Event Binding to single handler

I came across a situation where having single handler helps simplify the project. Does this have any impact on performance? Especially when the mouse move event called, having too many conditions have any impact on performance?
var myHandler = function(e){
if (e.type == 'mousemove'){
} else if (e.type == 'mouseover'){
} else if (e.type == 'mouseout'){
} else if (e.type == 'mousedown'){
} else if (e.type == 'mouseup'){
}
};
$('#Element').bind('mouseover mouseout mousedown mouseup mousemove', myHandler);
If you do need to handle all those events and you order the if-else statements by the frequency that the events are fired (as you already have) there is insignificant performance penalty, i.e. at most 4 short string comparisons. The following code tries to benchmark the performance of 10,000,000 string comparisons of fixed size:
$(function (){
Function.prototype.benchmark = function(name, times, args){
var iteration;
var start = new Date();
for (iteration=0; iteration<times; iteration++) {
var result = this.apply(this, args);
}
var end = new Date();
alert(name + " : " + (end-start));
}
function test(args){
return args[0] == "thisistest";
}
function overhead(args){
}
test.benchmark("string comparison", 10000000,["thisistesT"]);
//run same without the string comparison
overhead.benchmark("overhead", 10000000,["thisistesT"]);
});
Since the browser is not the only application on my PC the results vary between the executions, however, I very rarely got results of under 100ms in Chrome (remember that this is for 10,000,000 iterations).
Anyway, while your performance will not suffer from binding multiple events to a single function I really doubt that this will simplify your project. Having many if-else statements is usually considered a bad practice and a design flaw.
If you do this so that you can share state between the handlers by having them under the common scope of a function, you are better off having something like:
$(function (){
var elementSelector = "#Element";
var i = 0; //shared
var events = {
mouseover : function(){alert("mouseOver " + elementSelector + i++);},
mouseout : function(){alert("mouseOut " + elementSelector + i++);}
// define the rest of the event handlers...
};
var $target = $(elementSelector);
for(var k in events){
$target.bind(k, events[k]);
}
});
One more note regarding performance (plus code readability), switch is significantly faster than else ifs.
var myHandler = function(e){
switch(e.type){
case 'mousemove':
break;
case 'mouseover':
break;
case 'mouseout':
break;
case 'mousedown':
break;
case 'mouseup':
break;
}
};
For more detials you can tajke a look at Performance of if-else, switch or map based conditioning

Resources