2011-12-13 12 views
11

La creencia aceptada es que el uso de una construcción como Dim dict As New Dictionary tiene un rendimiento inferior al Dim dict As Dictionary/Set dict = New Dictionary.¿Es el mal funcionamiento de Excel VBA la creación automática de un mito?

La explicación es que el ejemplo anterior - auto-instanciación - difiere la instanciación hasta el primer uso de la variable dict. Y así, cada vez que se hace referencia a dict, el código compilado primero debe verificar si dict es igual a Nada.

Pero se me ocurre que el código compilado lo hace de todos modos. Obtendrá un error cada vez que intente utilizar una referencia de objeto que sea Nothing.

Entonces, en homenaje a la ciencia, hice algunas pruebas. Y los resultados sugieren que no hay diferencia de rendimiento entre los dos enfoques. (Ejecutar en Excel 2007)

Llamar "crear diccionario & agregar 2 elementos" 100.000 veces.

  • explícitos: 16,891ms/Auto: 16,797ms (94ms Auto más rápido)
  • explícitos: 16,797ms/Auto: 16,781ms (16ms Auto más rápido)

Invertir el orden de las llamadas de prueba :

  • Auto: 16,766ms/explícitos: 16,812ms (46ms Auto más rápido)
  • Auto: 16,828ms/explícitos: 16,813ms (15 ms explícitos más rápido)

Llamar "crear diccionario & agregar 6 elementos" 100.000 veces.

  • Auto: 17,437ms/explícitos: 17,407ms (30ms explícitos más rápido)
  • Auto: 17,343ms/explícitos: 17,360ms (17ms Auto más rápido)

Crear diccionario y suman 100.000 artículos.

  • Auto: 391ms/explícitos: 391ms (SAME)

Crear diccionario y suman 1.000.000 artículos.

  • Auto: 57,609ms/explícitos: 58,172ms (563ms Auto más rápido)
  • explícitos: 57,343ms/Auto: 57,422ms (79ms explícitos más rápido)

veo nada que indique que la auto-instanciación es una relación de bajo rendimiento para la creación de instancias explícita. (Para que quede claro, por otras razones, evitaría la auto-instanciación, pero estoy interesado en el ángulo de rendimiento aquí).

¿Es esto un mito?

ACTUALIZACIÓN

Permítanme poner por qué el argumento de rendimiento no tiene sentido para mí. Se dice que

x.Add("Key", "Item") 

en un objeto de auto-instancia es equivalente a la siguiente:

If x is Nothing then 
    Set x = New Dictionary 
End If 
x.Add("Key", "Item") 

lo que hace que se vea como "gastos generales aterradora" si está llamando esto miles de veces. Pero en el caso de instancias explícita, es exactamente la forma de la lógica generada en la versión compilada del código:

If x is Nothing Then 
    Err.Raise "Object variable not set..." 
End If 
x.Add("Key", "Item") 

No significa necesariamente que el auto es más largo, por lo que me estoy preguntando si había cualquier verdad a esto. Me pregunto si he identificado otro de los muchos mitos de rendimiento no probados.

+0

Realmente solo es la semántica diferente de "Nothing" la que establece 'As New' ligeramente separado de' Dim/Set'. Como dices, la llamada sobrecarga que implica una verificación de tipo de tiempo de ejecución es irrelevante dado que, a menos que el objeto verificado automáticamente * sea * 'Nada', no ocurre más que si fuera una referencia' Dim/Set'. –

+0

@Alex K, esta antigua guía de rendimiento dice * cada * referencia a la variable invocará una comprobación "Si X no es nada" en el caso automático, que una variable Dim/Set no mostrará. Por lo tanto, debe probar si se produce un golpe de rendimiento cada vez que acceda al objeto después de la declaración, en lugar de probar la declaración en sí. –

+0

@JP No es cierto. Busqué en Google esto después de otra pregunta que estaba viendo hoy. Ejemplo: http://www.cpearson.com/excel/classes.aspx Otro ejemplo: http://www.bettersolutions.com/vba/VUA113/LI912711911.htm –

Respuesta

5

Sé que es una decisión sagrada si está bien o no atenuarse como nuevo, pero nunca escuché que se dice que genera un rendimiento deficiente. La respuesta corta es Not Really. Sí, ensucia el código con controles innecesarios para ver si no es Nada, pero no notaría una diferencia de velocidad gracias a las máquinas de hoy. Es como decir "para recorrer más de 10000 caracteres es más rápido que 10001. Para empezar a ver cualquier diferencia, debe realizar un bucle de sus pruebas en términos más altos, como millones y decenas de millones.

Dicho esto Dim como nuevo está mal visto condiciones, sin que por razones de rendimiento.

  • se pierde la capacidad de controlar cuando se ha inicializado
  • se pierde la capacidad para comprobar si un objeto es Nada
  • diferencia de velocidad o no, lo hace la basura su código con control unescésario

Concedido si solo está utilizando VBA para automatizar algunas cosas de la hoja de trabajo o manipular datos, probablemente no le interesarán estos, pero en el momento en que vea código más sofisticado, perderá la capacidad de probar si un objeto es Nada y no controlar cuando se inicializa es enorme y puede generar un comportamiento inesperado, por no hablar de hacer una prueba de dolor en el trasero. Todo eso para guardar unas pocas líneas de código.

Luego están los micro-optimizadores que argumentarán que agregar algo a su código que no es necesario hace que el rendimiento sea pobre. Si bien están correctos de alguna manera, lo más probable es que ahorre 0.000000001 segundos en este caso.

+0

Estoy de acuerdo en que pierdes la capacidad de controlar cuando se inicializa; y creo que es un problema más serio que es prácticamente IMPOSIBLE establecer el objeto en Nada. Pero la pregunta es sobre la "verificación innecesaria": ¿es cierto? Después de todo, si escribo Dim x como Dictionary, entonces x.Add (1, "m") - Voy a obtener un error que dice "Variable de objeto no establecida", lo que significa que VBA compilado lo está comprobando de todos modos. –

+0

La comprobación durante la compilación y la comprobación durante el tiempo de ejecución son muy diferentes. Créanme, comprobar el tiempo de compilación es BUENO y dejarlo en tiempo de ejecución no lo es. :) Y cuando se arroja un error, no es porque lo haya comprobado y se haya dado cuenta de que no podría hacerlo, sino de TRATAR de hacer algo que no podría hacer. – aevanko

+0

+1 "perder la capacidad de probar si un objeto es Nada y no controlar cuándo se inicializa" - un programador debe tener el control, no el código. El beneficio en el rendimiento de no tener un control implícito de "No es nada" cuando se declara una variable es superado por esta consideración. – JimmyPena