30-seconds-of-code: Initializing an array of length `n`

Created on 26 May 2018  路  6Comments  路  Source: 30-seconds/30-seconds-of-code

Currently we use

Array.from({ length: n })

That's kind of verbose and a bit weird. I think we replaced Array(n).fill() with that, but there is also:

Array.from(Array(n))
[...Array(n)]

Which are nicer, I think.

In Chrome, the spread one is by far the fastest (10,000 iterations):

[...Array(1000)].map((_, i) => i)
// test: 512.635986328125ms

Array.from(Array(1000), (_, i) => i)
// test: 1093.662109375ms

Array.from({ length: 1000 }, (_, i) => i)
// test: 1252.54931640625ms

Array.from({ length: 1000 }).map((_, i) => i)
// test: 1302.962890625ms

It appears that using the second argument of Array.from() as the map instead of chaining .map offers almost no benefits in performance

discussion opinions needed

Most helpful comment

To be honest all of these are fairly slow

image

The problem with all of the methods is that they all require the creation and deletion of internal memory addresses for every operation.

If you don't know your array size or needed array size all of these techniques are kind of moot.

If you don't need an extremely high performance application where every address matters, the none of these matter.

We should go for readability and maintainability over performance. Here readable brevity counts the most. To that end we should compare those metrics above performance since I doubt anyone will use these over a function that calls a for loop in a high performance application and if they're at the point they need to squeeze that much performance out of their application then they already know to make that change.

To that end my preference leans towards Array.from({ length: n }) for those specific segments PURELY because like a good program it reads like a story:

An Array from a defined length

An Array from a spread Array

An Array from an Array

Out of these the first story is the most cognitively easy to understand. If you told that to any developer they'd instantly know how to go about it. That's a huge win. Especially since Arrays of predefined length are such a rare occurrence.

All 6 comments

I think we had a performance comparison and decided that Chrome is optimized for spread, but it's extremely slow on anything else.

In the same discussion, I think we decided to go with { length: n} for some reason, which I cannot remember. I definitely prefer it to Array(n).fill() and Array(n).from(Array(n)), but I'm not the only one with an opinion here, so let's vote on this (or someone could dig and find the original conversation on this topic).

I just tested Firefox (latest, mac) and spread is also faster. Not 2x like Chrome is but around 1.2x

I just run a JSPerf to check performance across multiple browsers. Here are my results on Windows 10:

Chrome

chrome

Edge

edge

Firefox

firefox

Opera

opera

The results are pretty clear here:

  • Spread and { length: 1000 }, (_, i) => i are the two clear winners out of the bunch.
  • Using .map with length is slightly slower than using the second argument.
  • Chrome is the only browser that is highly optimized for spreading arrays, while the rest show comparable performance between spreading and using our current technique.

So the question that arises is if we want to optimize for Chrome (around 80% of all users) and risk losing support for older browsers in a couple dozen snippets. I am not entirely set on either option, so any opinions would be useful here.

@fejes713, @skatcat31, @atomiks, @flxwu your thoughts?

To be honest all of these are fairly slow

image

The problem with all of the methods is that they all require the creation and deletion of internal memory addresses for every operation.

If you don't know your array size or needed array size all of these techniques are kind of moot.

If you don't need an extremely high performance application where every address matters, the none of these matter.

We should go for readability and maintainability over performance. Here readable brevity counts the most. To that end we should compare those metrics above performance since I doubt anyone will use these over a function that calls a for loop in a high performance application and if they're at the point they need to squeeze that much performance out of their application then they already know to make that change.

To that end my preference leans towards Array.from({ length: n }) for those specific segments PURELY because like a good program it reads like a story:

An Array from a defined length

An Array from a spread Array

An Array from an Array

Out of these the first story is the most cognitively easy to understand. If you told that to any developer they'd instantly know how to go about it. That's a huge win. Especially since Arrays of predefined length are such a rare occurrence.

@skatcat31 I really like the way you put this, that a good program should read like a story. I think we can stick with what we have as it doesn't have a huge impact in performance, is easy to read, doesn't harm compatibility etc. I'm closing for now, if spread somehow becomes faster over time across browsers, we can revisit this and see how we feel.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for any follow-up tasks.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Priyansh2001here picture Priyansh2001here  路  5Comments

Lucien-X picture Lucien-X  路  5Comments

GrosSacASac picture GrosSacASac  路  3Comments

kingdavidmartins picture kingdavidmartins  路  5Comments

skatcat31 picture skatcat31  路  5Comments