javascript - usar - jquery ejemplos basicos
¿Por qué el pop es más rápido que el cambio? (6)
Douglas Crockford, en JavaScript: The Good Parts , afirma que "el cambio suele ser mucho más lento que el pop". jsPerf confirma esto . ¿Alguien sabe por qué este es el caso? Desde un punto de vista poco sofisticado, parecen estar haciendo casi lo mismo.
Debido a que shift () reindexa la matriz, por lo que el método shift es muy lento en una matriz grande.
var array = [];
for(var i = 0;i< 1000000;i++){
array.push(i)
}
var start = new Date().getTime()
for(var i = 0; i< 100000; i++){
array.shift();
}
var duration = new Date().getTime() - start;// duration is so large, greater than 3 minutes
Pero la duración es de solo 8 ms cuando se usa la cola enlazada.
var LQueue = require(''linked-queue'')
var queue = new LQueue()
for(var i = 0;i< 1000000;i++){
queue.enqueue(i);
}
console.log("Queue length:"+ queue.length);
var start = new Date().getTime()
queue.dequeueAll(function(data){
})
var end = new Date().getTime();
console.log("Time:" + (end - start));// 8 ms
console.log("Queue length:"+ queue.length);
Estaba haciendo algunas pruebas en esto con node (que usa Chrome v8) y noté que para arreglos de hasta alrededor de 120k elementos, el rendimiento de shift es bastante cercano al pop. Una vez que obtienes más de 120K, parece disminuir drásticamente.
var sum;
var tests = [125000,130000];
console.log(JSON.stringify(process.versions));
tests.forEach(function(count) {
console.log(''Testing arrays of size '' + count);
var s1 = Date.now();
var sArray = new Array(count);
var pArray = new Array(count);
for (var i = 0; i < count ; i++) {
var num = Math.floor(Math.random() * 6) + 1
sArray[i] = num;
pArray[i] = num;
}
console.log('' -> '' + (Date.now() - s1) + ''ms: built arrays with '' + count + '' random elements'');
s1 = Date.now();
sum = 0;
while (pArray.length) {
sum += pArray.pop();
}
console.log('' -> '' + (Date.now() - s1) + ''ms: sum with pop() '' + count + '' elements, sum = '' + sum);
s1 = Date.now();
sum = 0;
while (sArray.length) {
sum += sArray.shift();
}
console.log('' -> '' + (Date.now() - s1) + ''ms: sum with shift() '' + count + '' elements, sum = '' + sum);
});
Salida:
{"http_parser":"1.0","node":"0.10.22","v8":"3.14.5.9","ares":"1.9.0-DEV","uv":"0.10.19","zlib":"1.2.3","modules":"11","openssl":"1.0.1e"}
Testing arrays of size 125000
-> 14ms: built arrays with 125000 random elements
-> 2ms: sum with pop() 125000 elements, sum = 436673
-> 6ms: sum with shift() 125000 elements, sum = 436673
Testing arrays of size 130000
-> 50ms: built arrays with 130000 random elements
-> 1ms: sum with pop() 130000 elements, sum = 455971
-> 54372ms: sum with shift() 130000 elements, sum = 455971
La diferencia puede ser despreciable: los ejecutores no optimizados pueden ejecutar shift
mucho más lento que el pop
, pero los optimizados no.
Puedes optimizar así:
let WrapArray = _=>{
//Ensure no other ref to `_`.
let numlike = _=>isNaN(_)?false:true
let num = _=>Number(_)
{
let shift_q = 0
return new Proxy(_, {
get(first_t, k){
switch(k){
case ''shift'': return (z={})=>(z.r=first_t[0 + shift_q], delete first_t[0 + shift_q++], z.r)
break; case ''length'': return first_t.length - shift_q
break; default: return first_t[numlike(k)?num(k) +/*todo overflowguard*/shift_q:k]
}
},
set(first_t, k, v){
switch(k){
case ''length'': first_t.length = v + shift_q
break; default: first_t[numlike(k)?num(k) +/*todo overflowguard*/shift_q:k] = v
}
},
has(first_t, k){
return (numlike(k)?num(k) +/*todo overflowguard*/shift_q:k) in first_t
},
deleteProperty(first_t, k){
delete first_t[numlike(k)?num(k) +/*todo overflowguard*/shift_q:k];return 543
},
apply(first_t, t, s){
first_t.call(t, s)
},
construct(first_t, s, t){
new first_t(...s)
},
})
}
}
(_=WrapArray([''a'',''b'',''c''])).shift()
console.log(_.length/*2*/, _[0]/*b*/, _[1]/*c*/, _[2]/*undefined*/)
Para eliminar el elemento devuelto sin volver a direccionar la matriz e invalidar todas las referencias a ella, shift()
requiere mover la matriz completa; pop()
simplemente puede restar 1 de su longitud.
Si cambias, tienes que copiar todos los elementos de la matriz hacia atrás. Para hacer estallar, solo necesita disminuir la longitud de la matriz. Técnicamente, una implementación podría solucionar esto, pero necesitaría almacenar una variable de ''cambio'' extra que le indique dónde está el verdadero comienzo de la matriz. Sin embargo, este tipo de operación no ha demostrado ser muy útil en la práctica y, por lo tanto, la mayoría de las implementaciones ahorran espacio al almacenar solo un inicio de puntero de matriz y un valor de longitud.
shift()
tiene que volver a indexar la matriz completa, mientras que pop()
no lo hace.
pop()
simplemente elimina el último elemento de la matriz. Por lo tanto, los elementos no se mueven; simplemente el .length
tiene que ser actualizado.
shift()
elimina el primer elemento de la matriz. Esto requiere una nueva indexación de todos los elementos en la matriz, de modo que [1]
convierta en [0]
y así sucesivamente.