Problema de rendimiento con "Medir"

Tengo un problema de rendimiento en mi aplicación. Esencialmente, hago clic en un botón y se completa una lista con datos vinculados a datos (esto está virtualizado debido a la gran cantidad de datos), y luego hago clic en otro botón que agregará una fila a una vista de lista asociada. Estoy siendo vago porque creo que es necesario ilustrar lo poco que sucede realmente en la interfaz de usuario.

Esto es lo que sé:

  • No veo el problema en mi robusta computadora de desarrollo con Win 7 Pro, ni en máquinas XP SP3 con especificaciones decentes. Solo lo veo en una determinada marca de computadoras portátiles (Lenovo ThinkPads) que ejecutan Win 7 Enterprise con 4 GB de RAM y CPU Core i5 (mucho más robusta que la computadora de escritorio XP).
  • Debido a los hallazgos mencionados anteriormente, no creo que esto sea un problema con el código.
  • Hice un perfil con la herramienta PerfView de Microsoft y noté lo que supondría que es un número increíblemente grande de llamadas a UIElement.Measure (nunca invocado directamente por nuestro código), algo que no veo cuando perfilo en las otras máquinas.
  • La computadora portátil tiene una resolución de 1360x780, así que pensé que tal vez la pequeña resolución estaba causando que la GPU renderizara los controles innecesariamente debido a algún enlace de datos que podría estar haciendo (lo que podría explicar la gran cantidad de llamadas a Measure()). Extendí la pantalla de la computadora portátil a mi monitor de 24" y no vi ninguna mejora.

En este momento estoy asumiendo que el problema es con la GPU. He actualizado el controlador sin mejoras.

  1. Aunque no creo que sea un problema con el código, ¿hay un WPF equivalente a "SuspendLayout ()"?
  2. ¿Hay alguna manera de perfilar el rendimiento de la GPU para ver si se está golpeando durante ciertos procesos?
  3. (toma lejana) ¿Alguien ha tenido problemas de rendimiento similares que parecen ser específicos de la computadora y sugerencias sobre cómo rastrearlos?

Lo siento si esta es una pregunta vaga. Intenté que cumpliera con los requisitos de uso de SO. Avísame si quieres más información.

Solo como un apéndice: el programa usa WPF, C# 4.0, el problema parece estar relacionado con los controles de Telerik (aunque no creo que sean sospechosos ya que los usamos en otros lugares sin problemas).

preguntado el 27 de julio de 12 a las 22:07

¿De verdad crees que no publicar código para ayudar? Si no sucede mucho, entonces no debería haber mucho código para publicar. -

Hay una gran cantidad de código que se activa, pero como mencioné antes, dado que no es un problema en otras computadoras, tanto en hardware más rápido como más lento, estoy convencido de que no es un problema de codificación. También he creado perfiles utilizando otros generadores de perfiles que analizan el código y sugieren lo mismo. -

WPFPerf le dará una idea de lo que está ocupando tantos ciclos, aunque parece que ya ha descubierto que está relacionado con el diseño. Creo que mi próximo paso sería averiguar qué control(es) tienen su lógica de diseño ejecutándose con más frecuencia en la computadora portátil. Podría darte algunas pistas para continuar. -

"Se activa una gran cantidad de código" no es coherente con "para ilustrar lo poco que sucede realmente en la interfaz de usuario". -

¿Qué tipo de lista tienes? Colección Observable? Supongo que cada vez que agrega un elemento, esto genera una notificación en su interfaz de usuario que luego genera una medida y un arreglo. A medida que agrega muchos elementos, obtiene muchas medidas y arreglos. blogs.msdn.com/b/nathannesbit/archive/2009/04/20/… podría ayudar, o vea cómo se implementa su lista en particular. También busque en CollectionViews. -

2 Respuestas

1. Responder

Para prevenir rampante MeasureOverride llamadas que se originan en WPF ContextLayoutManager:

protected override void OnChildDesiredSizeChanged(UIElement el)
{
    /* base.OnChildDesiredSizeChanged(el); */       // avoid rampant remeasuring
}

2. Cita relevante

UIElement.OnChildDesiredSizeChanged(UIElement) Method
  ...

Los programas OnChildDesiredSizeChanged(UIElement) El método tiene la implementación predeterminada de llamar InvalidateMeasure() en sí mismo. Una implementación típica sería: haga cualquier optimización que admita su propio elemento, y luego llame a la base OnChildDesiredSizeChanged(UIElement) de al menos uno de las ramas del código...

... la implicación (y el hecho del asunto) es que, para cualquier pase de diseño principal único originado por cualquier . de sus hijos, de los padres MeasureOverride será llamado adicionalmente, y probablemente extrañamente, una vez por cada de sus hijos cuyo tamaño también ha cambiado.

3. Discusión

En el caso de que varios niños cambien sus tamaños "al mismo tiempo", el padre generalmente detectará y tendrá en cuenta el nuevo diseño general entre todos de sus hijos por completo durante sólo el en el primer de estas llamadas. Esta es una práctica estándar en WPF, y es alentado por MeasureOverride(…) excluyendo deliberadamente cualquier indicación de algún niño desencadenante específico. Además del hecho de que en los casos más comunes no existe tal niño (ver enlace de arriba para más detalles), hace que el código para intentar cualquier tipo de "diseño parcial" sea oneroso. Pero sobre todo, ¿por qué cualquier cálculo de diseño querría continuar sin obtener primero todos las últimas medidas disponibles de todos modos?

Entonces vemos que después de un solo MeasureOverride llamada, desencadenada por el niño que resultó ser "primero" (no debería importar), el diseño del padre debería ser definitivo con respecto a todos de su información más reciente sobre el tamaño del niño. Pero esto no significa que haya cola OnChildDesiredSizeChanged las notificaciones—para otros niños cuyo(s) tamaño(s) también habían cambiado—han desaparecido. Esas llamadas todavía están pendientes con el padre y, a menos que la llamada de base virtual se abandone explícitamente (como se muestra en la viñeta #1), cada uno generará uno adicional, ahora extraño MeasureOverride llamada.

4. Advertencia

El código que se muestra aquí desactiva todos invalidaciones de medidas iniciadas por el niño, lo cual es apropiado para los casos en los que el padre prohibe deliberadamente tales cambios o ya está consciente de ellos. Esto no es raro; por ejemplo, incluye a cualquier padre que siempre determina y hace cumplir completamente el tamaño de sus hijos, o más generalmente, cualquier padre que solo adopta DesiredSize valores de sus hijos durante su propio pase de medida. Lo importante es que la medición del padre esté suficientemente garantizada por su propio padre solamente.

La situación en la que un padre podría desear cancelar algo de las notificaciones de medidas iniciadas por niños mientras se preservan/permiten otras dependerá naturalmente de circunstancias particulares adicionales. Parece más oscuro, por lo que no se aborda aquí.

Respondido 15 ago 21, 18:08

Resulta que es causado por un problema conocido de Microsoft. Intentaría explicarlo, pero no lo haré. Principalmente porque no puedo.

Artículo que habla de arreglo (ver publicación de Viðar el 3 de agosto de 2010):

Sitio de revisión de Microsoft: http://support.microsoft.com/kb/2484841/en-us

Solución: http://archive.msdn.microsoft.com/KB2484841/Release/ProjectReleases.aspx?ReleaseId=5583

contestado el 23 de mayo de 16 a las 15:05

"Trataría de explicarlo, pero no lo haré..." Lo suficientemente justo; lo di my mejor tiro en otro https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be en esta página. - Glenn Slayden

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.