ultimo - substring javascript ejemplo
Grandes subcadenas ~ 9000x más rápidas en Firefox que en Chrome: ¿por qué? (2)
El punto de referencia: http://jsperf.com/substringing
Por lo tanto, estoy iniciando mi primer proyecto del lado del cliente basado en navegador HTML5. Tendrá que analizar archivos de texto muy, muy grandes en, esencialmente, una matriz o matrices de objetos. Sé cómo voy a ir a codificarlo; Mi principal preocupación en este momento es obtener el código del analizador lo más rápido que pueda, y mi principal banco de pruebas es Chrome. Sin embargo, mientras observaba las diferencias entre los métodos de subcadena (no he tocado JavaScript en mucho, mucho tiempo), noté que esta referencia era increíblemente lenta en Chrome en comparación con FireFox. ¿Por qué?
Mi primer supuesto es que tiene que ver con la forma en que el motor JS de FireFox manejaría los objetos de cadena, y que para FireFox esta operación es una simple manipulación de punteros, mientras que para Chrome en realidad está haciendo copias en papel. Pero, no estoy seguro de por qué Chrome no haría la manipulación del puntero o por qué FireFox lo haría . ¿Alguien tiene alguna idea?
JSPerf parece estar arrojando mis resultados de Firefox, no mostrándolos en el BrowserScope. Para mí, estoy obteniendo 9,568,203 ± 1.44% Ops / seg en .substr()
en FF4.
Edición: Así que veo un resultado de rendimiento de FF3.5 ahí abajo, en realidad debajo de Chrome. Así que decidí probar mi hipótesis de punteros. Esto me llevó a una segunda revisión de mi prueba de subcadenas, que realiza 1,092,718±1.62%
Ops / seg en FF4 frente a 1,195±3.81%
Ops / seg en Chrome, hasta 1000 veces más rápido, pero sigue siendo una diferencia inexplicable en el rendimiento.
Un postscriptum: No, no me preocupa una sola cosa sobre Internet Explorer. Me preocupa intentar mejorar mis habilidades y conocer este idioma en un nivel más profundo.
¿Ha eliminado la lectura de .length
de sus resultados de referencia?
Creo que V8 tiene algunas representaciones de una cadena:
1. a sequence of ASCII bytes
2. a sequence of UTF-16 code units.
3. a slice of a string (result of substring)
4. a concatenation of two strings.
El número 4 es lo que hace que la cadena sea más eficiente.
Solo estoy adivinando, pero si están intentando agrupar dos punteros de cadena y una longitud en un espacio pequeño, es posible que no puedan almacenar en caché las longitudes grandes con los punteros, por lo que pueden terminar recorriendo la lista de enlaces unidos para calcular la longitud. Esto supone, por supuesto, que Array.prototype.join
crea cadenas de forma (4) a partir de las partes de la matriz.
Esto lleva a una hipótesis comprobable que explicaría la discrepancia, incluso ausentes copias de búfer.
EDITAR:
Miré a través del código fuente de V8 y StringBuilderConcat es donde empezaría a tirar, especialmente runtime.cc
.
En el caso de Spidermonkey (el motor JS en Firefox), una llamada substring()
simplemente crea una nueva "cadena dependiente": un objeto de cadena que almacena un puntero a la cosa que está fuera de una subcadena y las compensaciones de inicio y fin. Esto es precisamente para hacer que la substring()
rápida, y es una optimización obvia dada las cadenas inmutables.
En cuanto a por qué V8 no hace eso ... Una posibilidad es que V8 esté tratando de ahorrar espacio: en la configuración de la cadena dependiente, si mantiene la subcadena pero olvida la cadena original, la cadena original no puede ser controlada porque La subcadena está utilizando parte de sus datos de cadena.
En cualquier caso, solo miré la fuente V8, y parece que simplemente no hacen ningún tipo de cadenas dependientes; Sin embargo, los comentarios no explican por qué no lo hacen.
[Actualización, 12/2013]: Unos meses después de dar la respuesta anterior, V8 agregó soporte para cadenas dependientes, como señala Paul Draper.