Aunque esta pregunta ya ha sido respondida, he pensado que podría intervenir y dar mi opinión.
DESCARGO DE RESPONSABILIDAD : Trabajé para ESRI en el equipo de GeoDatabase durante algunos años y estuve a cargo del mantenimiento de varias partes del código de GeoDatabase (Versioning, Cursors, EditSessions, History, Relationship Classes, etc etc).
Creo que la mayor fuente de problemas de rendimiento con el código de ESRI es no entender las implicaciones del uso de diferentes objetos, en particular, los "pequeños" detalles de las diversas abstracciones de la base de datos geográfica. Así que muy a menudo, la conversación cambia al lenguaje que se utiliza como culpable de los problemas de rendimiento. En algunos casos puede serlo. Pero no siempre. Empecemos con la discusión sobre el lenguaje y vayamos hacia atrás.
1.- El lenguaje de programación que elijas sólo importa cuando estés haciendo algo complicado, en un bucle cerrado. La mayoría de las veces, este no es el caso.
El gran elefante en la habitación es que en el núcleo de todo el código de ESRI, tienes ArcObjects - y ArcObjects está escrito en C++ utilizando COM . La comunicación con este código tiene un coste. Esto es cierto para C#, VB.NET, python, o cualquier otra cosa que esté utilizando.
Se paga un precio en la inicialización de ese código. Puede ser un coste insignificante si lo haces una sola vez.
A continuación, se paga un precio por cada vez que se interactúa con ArcObjects.
Personalmente, tiendo a escribir código para mis clientes en C#, porque es bastante fácil y rápido. Sin embargo, cada vez que quiero mover datos o hacer algún procesamiento para grandes cantidades de datos que ya está implementado en Geoprocessing Simplemente inicializo el subsistema de scripting y paso mis parámetros. ¿Por qué?
- Ya está implementado. Entonces, ¿por qué reinventar la rueda?
- En realidad puede ser más rápido . "¿Más rápido que escribirlo en C#?" Sí. Si implemento, por ejemplo, la carga de datos manualmente, significa que pago el precio del cambio de contexto de .NET en un bucle cerrado. Cada GetValue, Insert, ShapeCopy tiene un coste. Si hago la única llamada en GP, todo el proceso de carga de datos ocurrirá en la implementación real de GP - en C++ dentro del entorno COM. No pago el precio del cambio de contexto porque no hay ninguno - y por lo tanto es más rápido.
Ah, sí, entonces la solución es utilizar muchas funciones de geoprocesamiento. En realidad, hay que tener cuidado.
2. La GP es una caja negra que copia datos (potencialmente innecesarios) por
Es un arma de doble filo. Es una caja negra que hace algo de magia internamente y escupe resultados, pero esos resultados se duplican muy a menudo. 100.000 filas pueden convertirse fácilmente en 1.000.000 de filas en el disco después de haber pasado los datos por 9 funciones diferentes. Usar sólo funciones de GP es como crear un modelo lineal de GP, y bueno...
3. Encadenar demasiadas funciones GP para grandes conjuntos de datos es muy ineficiente. Un modelo de GP es (potencialmente) equivalente a ejecutar una consulta de una manera realmente muy tonta
No me malinterpretes. Me encantan los Modelos GP - me ahorran escribir código todo el tiempo. Pero también soy consciente de que no es la forma más eficiente de procesar grandes conjuntos de datos.
¿Has oído hablar alguna vez de un Planificador de consultas ? Su trabajo es mirar la sentencia SQL que quieres ejecutar, generar un plan de ejecución en forma de grafo dirigido que se parece mucho a un Modelo GP , mira las estadísticas almacenadas en la db, y elige el el orden más óptimo para ejecutarlas . GP se limita a ejecutarlas en el orden en que las pones porque no tiene estadísticas para hacer algo más inteligente - usted es el planificador de la consulta . ¿Y adivina qué? El orden en el que se ejecutan las cosas depende en gran medida del conjunto de datos. El orden en el que se ejecutan las cosas puede marcar la diferencia entre días y segundos, y eso lo decides tú.
"Estupendo", dirás, no voy a guionizar las cosas yo mismo y voy a tener cuidado con cómo escribo las cosas. Pero, ¿entiendes las abstracciones de las bases de datos geográficas?
4.No entender las abstracciones de las bases de datos geográficas puede ser un problema.
En lugar de señalar cada una de las cosas que pueden suponer un problema, permítanme señalar algunos errores comunes que veo todo el tiempo y algunas recomendaciones.
- Comprender la diferencia entre Verdadero/Falso para los cursores de reciclaje . Esta pequeña bandera puesta a true puede hacer que el tiempo de ejecución sea órdenes de magnitud más rápido.
- Ponga su mesa en LoadOnlyMode para la carga de datos. ¿Por qué actualizar el índice en cada inserción?
- Comprenda que aunque IWorkspaceEdit::StartEditing tiene el mismo aspecto en todos los espacios de trabajo, son bestias muy diferentes en cada fuente de datos. En un GDB de empresa, es posible que tenga un sistema de versiones o soporte para transacciones. En los shapefiles, tendrá que ser implementado de una manera muy diferente. ¿Cómo se implementa la función de deshacer/rehacer? ¿Es necesario activarlo (sí, puede suponer una diferencia en el uso de la memoria)?
- La diferencia entre las operaciones por lotes, o las operaciones de una sola fila. Un ejemplo GetRow vs GetRows - esta es la diferencia entre hacer una consulta para obtener una fila o hacer una consulta para obtener varias filas. Un bucle cerrado con una llamada a GetRow significa un rendimiento horrible y es el culpable nº 1 de los problemas de rendimiento
- Utilice UpdateSearchedRows
- Comprender la diferencia entre CreateRow y CreateRowBuffer . Enorme diferencia en el tiempo de ejecución de la inserción.
- Entienda que IRow::Store y IFeature::Store desencadena un proceso superpesado polimórfico operaciones. Esta es probablemente la razón #2 culpable del rendimiento realmente lento. No sólo guarda la fila, este es el método que se asegura de que su red geométrica está bien, que el editor de ArcMap recibe una notificación de que una fila ha cambiado, que notifica a todas las clases de relación que tienen algo que ver con esta fila validar para asegurarse de que la cardinalidad es válida, etc. Usted no debe ser la inserción de nuevas filas con esto, usted debe ser el uso de un InsertCursor ¡!
- ¿Quiere (necesita) hacer esas inserciones en una EditSession? Hace un enorme diferencia si lo haces o no. Algunas operaciones lo requieren (y hacen las cosas más lentas), pero cuando no lo necesites, omite las funciones de deshacer/rehacer.
- Los cursores son recursos caros. Una vez que se tiene el manejo de uno, se garantiza que se tendrá Coherencia y aislamiento y eso tiene un coste.
- Almacene en caché otros recursos como las conexiones a la base de datos (no cree y destruya su referencia al espacio de trabajo) y los manejadores de las tablas (cada vez que abra o cierre una, es necesario leer varias tablas de metadatos).
- Poner FeatureClasses dentro o fuera de un FeatureDataset hace una gran diferencia en el rendimiento. Es no se entiende como un elemento de organización.
5.Y por último y no menos importante...
Comprender la diferencia entre Operaciones ligadas a la E/S y a la CPU
Sinceramente, he pensado en extenderme más en cada uno de esos temas y quizás hacer una serie de entradas en el blog que cubran cada uno de esos temas, pero la lista de pendientes de mi calendario me abofeteó en la cara y empezó a gritarme.
Mis dos centavos.