techfort / PowerArray

Boosted Performance Array
248 stars 16 forks source link

PowerArray constructor is too slow. #22

Open Hypercubed opened 9 years ago

Hypercubed commented 9 years ago

Intro

I've put together some Array speed tests for testing the speed of various "fast" array methodologies. I've been trying to implement fast version of concat in PowerArray. However, the PowerArray constructor is too slow. This in turn makes methods that return arrays (map, filter, concat) slow. The constructor is slow, in part, because of the cost of creating a new object (in other words new PowerArray() is slower new Array() which is slower than []) and also because recasting an existing array as a PowerArray requires copying each element to the new object. My approach in Hypercubed/BoostArray is to attach BoostArray prototype methods to normal arrays (or to the Array prototype), therefore never/rarely creating new objects. This method will not work in PowerArray which must create a new instance (different philosophies between the two projects).

Proposal

Therefore, I propose a new constructor in PowerArray based on the very detailed article How ECMAScript 5 still does not allow to subclass array by kangax.

function PowerArray() {
    var arr = [];
    arr.push.apply(arr, arguments);
    arr.__proto__ = PowerArray.prototype;
    return arr;
}

or the modified version consistent with current implementation.

function PowerArray(array) {
    var load = (arguments.length > 0) ? array.slice(0) : [];
    load.__proto__ = PowerArray.prototype;
    return load;
}

Proposed PowerArray constructor vs. existing PowerArray constructor

Pros:

techfort commented 9 years ago

Hey Jayson, agreed with everything you said. The biggest problem for me is represented by the proto non standard property, is this going to kill PowerArray in IE? I'd assume we can even implement some logic on whether to use or not proto if we are in an IE environment, but it sounds ugly at best.

Hypercubed commented 9 years ago

If you look at the table at the end of the article I linked above (http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/) I think it shows that Direct Extension (what I have done in BoostArray) is the most compatible method. According to MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto) __proto__ is deprecated but compatible with IE >= 11. In ECMAScript 6 they add Object.setPrototype() which can be shimmed as:

Object.setPrototypeOf = function(oInstance, oProto) {
  oInstance.__proto__ = oProto;
  return oInstance;
};

Unfortunately I don't see any other way to make a fast constructor.

tomByrer commented 9 years ago

Could have both ways; comparable & fast constructor. Bit of extra work since it would likely require a build tool to split the 2 versions (like lodash does). But some will appreciate having a better targeted version for their use-case.