c# - ¿Debo preocuparme por la velocidad del diccionario.NET?
arrays optimization (12)
Hola, crearé un proyecto que usará búsquedas de diccionario e inserciones un poco. ¿Es esto algo de qué preocuparse?
Sí. Siempre es aconsejable considerar los factores de rendimiento por adelantado.
La forma que debe tomar su inquietud es la siguiente: su inquietud debería alentarlo a escribir especificaciones de desempeño realistas y enfocadas en el usuario. Debería alentarlo a comenzar a escribir las pruebas de rendimiento temprano y ejecutarlas con frecuencia, de modo que pueda ver cómo cada cambio en el producto afecta el rendimiento. De esa manera, se le informará inmediatamente cuando un cambio de código provoque un cambio en el rendimiento que afectará al usuario. Y debería alentarlo a que ejecute los perfiles con frecuencia, de modo que esté razonando sobre el rendimiento basado en mediciones empíricas, en lugar de conjeturas y presentimientos aleatorios.
Además, si hago benchmarking y eso y es realmente malo, ¿cuál es la mejor manera de reemplazar el diccionario con otra cosa?
La mejor manera de hacer esto es construir una capa de abstracción razonable. Si tiene una clase (o interfaz) que representa el tipo de datos abstractos "insertar" y "buscar", entonces puede reemplazar sus elementos internos sin cambiar ninguna de las personas que llaman.
Tenga en cuenta que agregar una capa de abstracción en sí tiene un costo de rendimiento. Si su perfil muestra que la capa de abstracción es demasiado costosa, si el par de nanosegundos adicionales por llamada es demasiado, es posible que deba deshacerse de la capa de abstracción. Una vez más, esta decisión será impulsada por datos de rendimiento del mundo real.
¿Sería más rápido usar una matriz con claves "hash"? Eso no ayudaría en el tiempo de inserción, ¿verdad?
Es posible que ni usted ni nadie que lea esto pueda saber cuál es más rápido hasta que lo escriba en ambos sentidos y luego lo evalúe en las condiciones del mundo real . Hacerlo en condiciones de "laboratorio" sesgará tus resultados; Necesitará comprender cómo funcionan las cosas cuando el GC está bajo una presión de memoria realista, y así sucesivamente. También deberías preguntarnos qué caballo correrá más rápido en el Derby de Kentucky del próximo año. Si supiéramos la respuesta con solo mirar la forma de carrera, todos seríamos ricos ya. ¡No puede esperar que alguien sepa cuál de los dos códigos de código completamente hipotéticos y no escritos será más rápido en condiciones no especificadas!
Estaré creando un proyecto que utilizará búsquedas de diccionario e inserciones un poco. ¿Es esto algo de qué preocuparse?
Además, si hago benchmarking y eso y es realmente malo, ¿cuál es la mejor manera de reemplazar el diccionario con otra cosa? ¿Sería más rápido usar una matriz con claves "hash"? Eso no ayudaría en el tiempo de inserción, ¿verdad?
Además, no creo que esté optimizando a nivel micro porque esto realmente será una parte importante del código en un servidor de producción, por lo que si se necesitan 100 ms adicionales para completar, buscaremos nuevas formas de manejar esto.
Estás micro-optimizando. ¿Aún tienes código de trabajo? Recuerde: "Si no funciona, no importa lo rápido que no funcione". (Mich Ravera) http://www.codingninja.co.uk/best-programmers-quotes/ .
No tienes idea de dónde estarán los cuellos de botella y ya estás concentrado en el Diccionario. ¿Y si el problema está en otra parte?
- ¿Cómo sabes cómo se implementa la clase Dictionary? Tal vez ya utiliza una matriz con claves hash!
PS Es realmente ".NET Dictionaries", no "C # Dictionaries", porque C # es solo uno de varios lenguajes de programación que usan el framework .
Echa un vistazo a C # HybridDictionary Usage
Esta clase se recomienda para casos en los que se desconoce la cantidad de elementos en un diccionario. Aprovecha el rendimiento mejorado de un ListDictionary con pequeñas colecciones y ofrece la flexibilidad de cambiar a un Hashtable que maneja colecciones más grandes mejor que ListDictionary.
Es posible que desee ver la clase KeyedCollection en System.ObjectModel. De la descripción de MSDN, "proporciona la clase base abstracta para una colección cuyas claves están incrustadas en los valores".
Espere y vea si el rendimiento de su aplicación está por debajo de las expectativas.
Si es así, use un generador de perfiles para determinar si la búsqueda del diccionario es la fuente del problema
Si es así, realice algunas pruebas con datos representativos para ver si otra opción de lista sería más rápida.
En resumen, no , en general no debe preocuparse por el rendimiento de los detalles de la implementación hasta después de tener un problema.
Haría un punto de referencia del Diccionario, HashTable (HashSet en .NET), y quizás una clase local, y vería cuál funciona mejor bajo sus condiciones de uso típicas.
Normalmente diría que está bien (inserte la cita de eyaculación precoz favorita de aquí), pero si esto es una parte esencial de la aplicación, Benchmark, Benchmark, Benchmark.
La única preocupación que se me ocurre es que la velocidad del diccionario depende de que la clase clave tenga un método GetHashCode razonablemente rápido. Las búsquedas e inserciones son muy rápidas, por lo que no debería tener ningún problema allí.
Con respecto al uso de una matriz, eso es lo que hace la clase Dictionary. Actualmente utiliza dos matrices, una para las claves y otra para los valores.
Si tuviera algún problema de rendimiento con un diccionario, sería bastante fácil crear un contenedor para cualquier tipo de almacenamiento, que tenga los mismos métodos y comportamiento que un diccionario para que pueda reemplazarlo sin problemas.
No estoy seguro de que alguien haya respondido realmente esta parte todavía:
Además, si hago benchmarking y eso y es realmente malo, ¿cuál es la mejor manera de reemplazar el diccionario con otra cosa?
Para esto, siempre que sea posible, declare sus variables como IDictionary<TKey, TValue>
. Esa es la interfaz principal de la que deriva Dictionary. (Supongo que si le importa mucho el rendimiento, entonces no está considerando colecciones no genéricas). Luego, en el futuro, puede cambiar la clase de implementación subyacente sin tener que cambiar ninguno de los códigos que lo utilizan. diccionario. Por ejemplo:
IDictionary<string, int> myDict = new Dictionary<string, int>();
Puedes considerar usar la biblioteca C5 . He encontrado que es muy rápido y cuidadosamente diseñado. Otros en han encontrado lo mismo. Con C5, tiene la opción de usar interfaces de tipo general (con un I) o directamente las estructuras de datos debajo. Naturalmente, las interfaces le permiten intercambiar diferentes implementaciones, pero en las pruebas de rendimiento descubrí que las interfaces le costarán.
Si su aplicación es multiproceso, entonces la parte clave del rendimiento será sincronizar este Diccionario correctamente.
Si es de un solo hilo, es casi seguro que el cuello de botella sea en otra parte. Como leer estos objetos desde donde los estés leyendo.
Yo uso el diccionario para el servidor de transmisión UDP. Cada vez que llega un paquete, ejecuta Dictionary.ContainsKey y Dictionary [Key], y funciona muy bien (gran número de clientes). Tenía preocupaciones cuando estaba haciendo la cosa, pero resultó que era la última cosa por la que debería preocuparme.
La clase Dictionary<TKey, TValue>
se implementa realmente como una tabla hash que hace que las búsquedas sean muy rápidas (cerca de O (1)). Consulte la documentación de la API para obtener más información. Dudo que puedas hacer una mejor implementación tú mismo.