72 votes

Pourquoi la lecture en boucle d'un tableau est-elle plus rapide que la fonction native `indexOf` de JavaScript ?

Pourquoi la lecture en boucle d'un tableau est-elle tellement plus rapide que la méthode native JavaScript indexOf ? Y a-t-il une erreur ou quelque chose que je n'ai pas pris en compte ? Je m'attendais à ce que les implémentations natives soient plus rapides.

                For Loop        While Loop      indexOf
Chrome 10.0     50,948,997      111,272,979     12,807,549
Firefox 3.6     9,308,421       62,184,430      2,089,243
Opera 11.10     11,756,258      49,118,462      2,335,347   

http://jsben.ch/#/xm2BV

1voto

Jon J Points 331

Il peut être intéressant de noter que si tout ce que vous essayez de faire est de conserver une liste d'éléments et d'en vérifier l'existence (par exemple, éviter d'ajouter des ID en double à un tableau), il serait beaucoup plus rapide de conserver un OBJECT avec des clés qui reflètent chaque ID. Si vous pensez que je me trompe, comparez ce qui suit avec un tableau + indexOf. On parle de 181 ms pour la méthode objet contre 1 MINUTE pour la méthode indexOf du tableau.

var objs = []
var i_uid = {} // method 1
var a_uid = [] // method 2
var total_count = 100000, idLen = 5
var ts, te, cObj = 0

// method 1
ts = new Date()
while (cObj < total_count) {
    var u = uid(idLen),
        o = {
            uid: u,
            text: 'something',
            created: new Date()
        }
    if (!i_uid[u]) { // ensure unique uids only
        objs.push(o)
        i_uid[u] = cObj // current array position as placeholder
        cObj++
    }
    else {
        console.log('unique violation [duplicate uid', u, ']')
    }
}
te = new Date()
console.log('loaded ' + total_count + ' with object method in', (te - ts), 'ms')

i_uid = {} // free-up
cObj = 0 // reset
objs = [] // reset

// method 2
ts = new Date()
while (cObj < total_count) {
    var u = uid(idLen),
        o = {
            uid: u,
            text: 'something',
            created: new Date()
        }
    if (a_uid.indexOf(u) == -1) { // ensure unique uids only
        objs.push(o)
        a_uid.push(u)
        cObj++
    }
    else {
        console.log('unique violation [duplicate uid', u, ']')
    }
}
te = new Date()
console.log('loaded ' + total_count + ' with array + indexOf method in', (te - ts), 'ms')

function uid(l) {
    var t = '',
        p = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
        pl = p.length
    for (var i = 0; i < l; i++)
        t += p.charAt(Math.floor(Math.random() * pl))
    return t
}

1voto

efkan Points 6726

Nous pouvons nous fier à une simple boucle for à chaque fois.

J'ai écrit le code ci-dessous pour découvrir la réponse à cette question. Il est également exécutable . Il montre qu'un simple for loop est la meilleure solution si l'on considère performance .

(Le code est également disponible sur jsfiddle )

console.clear()

let a = []
// populating array data
for (let i = 0; i < 100000; i++) {
    a.push(i)
}

let testNum = 90000
let found
let totalMS4ForLoop = 0
let totalMS4IndexOf = 0
let start
let end
// simulating 10000 requests which are come consecutively
for (o = 0; o < 10000; o++) {

  start = Date.now()
  for (let i = 0; i < a.length; i++) {
    if (a[i] == testNum) { found = a[i]; break }
  }
  end = Date.now()
  totalMS4ForLoop += end - start

  start = Date.now()
  found = a[a.indexOf(testNum)]
  end = Date.now()
  totalMS4IndexOf += end - start

}

console.log("10000 for-loop executions took total " + totalMS4ForLoop + " ms.")
console.log("10000 indexOf executions took total " + totalMS4IndexOf + " ms.")

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X