2010-03-23 23 views
10

Tengo un formulario con un área de texto que puede contener grandes cantidades de contenido (por ejemplo, artículos para un blog) editado utilizando uno de varios editores de texto enriquecido de terceros. Estoy tratando de implementar algo así como una característica de autoguardado, que debe enviar el contenido a través de ajax si se cambia. Sin embargo, tengo que evitar el hecho de que algunos de los editores que tengo como opciones no admiten un indicador "isdirty" o un evento "onchange" que pueda usar para ver si el contenido ha cambiado desde el último guardado.Comparación de cadenas grandes en JavaScript con un hash

Así que, como solución, lo que me gustaría hacer es mantener una copia del contenido en una variable (llamémoslo lastSaveContent), desde el último guardado, y compararlo con el texto actual cuando el " autoguardar "la función se dispara (en un temporizador) para ver si es diferente. Sin embargo, me preocupa cuánta memoria podría ocupar con documentos muy grandes.

¿Sería más eficiente almacenar algún tipo de hash en la variable lastSaveContent, en lugar de toda la cadena, y luego comparar los valores de hash? Si es así, ¿puedes recomendar un buen plugin de biblioteca/jquery de JavaScript que implemente un hash apropiado para este requisito?

+0

Probablemente nunca ocurra en su caso de uso, pero para el lector casual que aterriza aquí en busca de javascript y hash (como yo), podría valer la pena señalar que comparar dos valores hash es * no * el Al igual que la comparación de dos cadenas, hash puede (y voluntad) colisionar, es decir, el mismo hash para dos cadenas diferentes. Por lo tanto, en muchos casos de uso, debe realizar una comparación completa si obtiene el mismo valor hash de todos modos. –

+0

Buen punto. Además, en caso de que los lectores se pregunten, la razón por la que los objetos Hashtable, como los encontrados en muchas API de colecciones, aún funcionan a pesar de esto es porque contienen funcionalidad para manejar estas colisiones cuando dos claves producen el mismo hash. – user4815162342

Respuesta

19

En resumen, es mejor que solo almacene y compare las dos cadenas.


Calculando un hash adecuada es no barato. Por ejemplo, consulte pseudo code o actual JavaScript implementation para calcular el hash MD5 de una cadena. Además, todas las implementaciones de hash apropiadas requerirán enumerar los caracteres de la cadena de todos modos.

Por otra parte, en el contexto de la informática moderna, una cadena tiene que ser realmente , realmente mucho antes de compararla con otra cadena es lento. Lo que estás haciendo aquí es efectivamente una micro-optimización. La memoria no será un problema, ni la CPU realizará ciclos para comparar las dos cadenas.

Al igual que con todos los casos de optimización: cheque que este es en realidad un problema antes de resolverlo. En una prueba rápida que hice, calcular y comparar 2 sumas MD5 tomó 382ms. Comparar las dos cadenas directamente tomó 0ms. Esto estaba usando una cadena que tenía 10000 palabras de largo. Ver http://jsfiddle.net/DjM8S.

Si realmente lo veo como un problema, también consideraría seriamente utilizar una comparación de personas pobres; y simplemente comparando la longitud de las 2 cuerdas, para ver si han cambiado o no, en lugar de las comparaciones de cuerdas reales.

..

+0

Bien, digamos que el usuario quería publicar un capítulo de una novela en su lugar. ¿Cuánto tiempo tendrían que ser los artículos para considerar la longitud de un "gran extracto de la Biblia"? – user4815162342

+2

MD5'ing la cadena, luego comparando eso con la suma de md5 "anterior", toma 382ms. La comparación básica de cadenas toma 0ms; esto es usando una cadena que tiene ~ 10000 palabras de largo. (http://www.jsfiddle.net/DjM8S/) – Matt

+0

Gracias. Esta es la mejor respuesta de los dos, y el tipo de respuesta que estaba buscando (aunque la otra respuesta también es informativa). Yo votaría por ello, pero aparentemente como nuevo usuario no tengo suficiente reputación. – user4815162342

4

Un hash MD5 se usa a menudo para verificar la integridad de un archivo o documento; debería funcionar para tus propósitos. Here es un buen artículo sobre cómo generar un hash MD5 en Javascript.

+0

Información útil, pero si no necesito molestarme con esto, como sugirió la otra respuesta, entonces tengo que mantener un poco menos de código. – user4815162342

1

Hice un JSperf rev que podría ser útil aquí para medir el rendimiento. ¡Agregue diferentes revisiones y diferentes tipos de cheques a los que hice!

http://jsperf.com/long-string-comparison/2

encontré dos resultados principales

  • Cuando las cadenas se un rendimiento idéntico es asesinada; de ~ 9000000 OPS/s a ​​~ 250 ops/seg (cromo)
  • La versión de 64 bits de IE9 es mucho más lento en mi PC, los resultados de las mismas pruebas:

    +------------+------------+ 
    | IE9 64bit | IE9 32bit | 
    +------------+------------+ 
    | 4,270,414 | 8,667,472 | 
    | 2,270,234 | 8,682,461 | 
    +------------+------------+ 
    

Tristemente , jsperf registró ambos resultados como simplemente "IE 9".

Incluso una mirada precursora en el rendimiento de JS MD5 me dice que es muy, muy lento (al menos para grandes cadenas, ver http://jsperf.com/md5-shootout/18 - picos a 70 ops/sec). Me gustaría llegar al extremo de probar AJAX el cálculo del hash o la comparación con el servidor, pero no tengo tiempo para probarlo, ¡lo siento!

+0

Y también, http://stackoverflow.com/a/10542872/694325. – Nenotlep