Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial Internet of Things >> Incrustado

Cómo garantizar el mejor rendimiento de la máquina de estado Qt

Si usa Qt para el desarrollo de aplicaciones y si usa máquinas de estado, entonces es probable que esté utilizando el marco de la máquina de estado Qt. Por lo tanto, definirá la máquina de estado utilizando C ++ o SCXML sin formato. Un enfoque alternativo es generar código C ++ a partir de diagramas de máquina de estados. Este artículo compara estos enfoques, teniendo en cuenta la funcionalidad, la aplicabilidad y el rendimiento.

Apuesto a que, como desarrollador de software, ya ha implementado toneladas de declaraciones de cambio de caso más o menos complicadas. Esto es al menos cierto para mí, y gran parte de esta codificación de cambio de caso no era más que la implementación de diversas máquinas de estado. Esta es la forma más fácil de comenzar a programar máquinas de estado si no tiene nada más a mano que el lenguaje de programación de su elección. Si bien el inicio es fácil, dicho código se vuelve cada vez menos fácil de mantener a medida que aumenta la complejidad de la máquina de estado. Al final, estará convencido de que no desea continuar implementando máquinas de estado manualmente de esta manera. (Por cierto, supongo que sabes qué son las máquinas de estado).

Implementación de máquinas de estado

Existen diferentes alternativas para implementar máquinas de estado. Una de las mejores formas, especialmente cuando está utilizando un lenguaje de programación orientado a objetos como C ++, es aplicando el patrón de estado. Este enfoque utiliza clases estatales y, a menudo, también clases de transición. Luego, se define una máquina de estado creando instancias de clases de estado y cableándolas usando instancias de clases de transición. En este caso, un marco ayuda mucho a reducir el tamaño del código y el esfuerzo de implementación.

El marco de la máquina de estado Qt es un buen ejemplo. Esta API le permite "configurar" una máquina de estado utilizando código compacto. No tiene que preocuparse por los detalles de la semántica de ejecución de la máquina de estado, ya que estos ya están implementados por el marco. Todavía tiene que escribir código y, a medida que su máquina de estados se vuelve más compleja y contiene algunas docenas o incluso cientos de estados, será muy difícil obtener una descripción general. Una imagen vale más que mil palabras y el conocido concepto de diagramas de estado ayuda a superar esta limitación. El propio Qt proporciona soporte para State Chart XML (SCXML), que es un estándar W3C. Como escribir XML a mano no es divertido, Qt Creator también incluye un editor gráfico de estado simple.

Independientemente del enfoque de implementación concreto, utilizar una sintaxis gráfica es la mejor opción para editar y comprender las máquinas de estado. Dichos modelos gráficos no solo pueden ser representados textualmente por lenguajes como SCXML, sino que también pueden usarse para generar cualquier tipo de código fuente de lenguaje de programación, como una máquina de estado basada en switch-case en C ++ simple - o código C ++ que configura instancias de QStateMachine. Si utiliza una herramienta que haga esa transformación por usted, puede evitar el dolor de escribir a mano el código de máquina de estado. Eleva los tres enfoques de implementación al mismo nivel de usabilidad. Sin embargo, las implementaciones siguen siendo fundamentalmente diferentes. Este artículo trata sobre la comparación de su comportamiento en tiempo de ejecución y especialmente su rendimiento.


UnsplashPhoto de Austris Augusts en Unsplash

Los competidores

Entonces, ¿qué pasa con el rendimiento? ¿En qué se diferencian los enfoques disponibles con respecto a los ciclos de CPU requeridos? Para obtener algunos números concretos, configuré un conjunto de pruebas de rendimiento. La primera parte compara las diferentes estrategias de implementación. Estos son los competidores:

  1. Intérprete SCXML:la máquina de estado de prueba se define mediante SCXML y se ejecuta mediante QSCXMLStateMachine de Qt clase.
  2. Patrón de estado:la máquina de estado de prueba se implementa mediante QStateMachine clases.
  3. Código C ++ simple:la máquina de estado de prueba se implementa mediante una clase C ++ que aplica un enfoque básico basado en el cambio de mayúsculas y minúsculas.

Nota:el código para estos ejemplos se puede encontrar aquí.

Las dos primeras variantes implican el uso de conceptos de Qt como señales y ranuras, así como el uso de una cola de eventos de Qt, mientras que una implementación de C ++ simple no requiere esta infraestructura. Para que los enfoques sean más comparables, el conjunto de pruebas incluye dos escenarios de prueba más:

Esto permite comparar el impacto del uso de señales y slots por un lado y el uso de QEvents por otro lado, en comparación con la implementación simple de C ++, ya que el código de ejecución de la máquina de estado es idéntico en todos los casos, pero simplemente envuelto de manera diferente.

La máquina de estado de prueba

Para probar a los cinco competidores, definí la máquina de estado que se muestra en la fig. 1 para el escenario de prueba básico.


Figura 1:La máquina de estado de prueba, creada con YAKINDU Statechart Tools. (Fuente:Autor)

La máquina de estado de prueba es una máquina de estado plano simple. Define seis estados A a F y recorre los estados. Dos eventos de entrada e1 y e2 se definen, que activan alternativamente transiciones de estado. Cuando tiene lugar una transición de estado, también se ejecuta una acción simple. Cada acción de transición simplemente agrega 10 a una variable de diagrama de estado llamada x . La transición del estado F a A además eleva (o emite) el out evento o .


Figura 2:La máquina de estado de prueba como modelo SCXML en Qt Creator. (Fuente:Autor)

Esta máquina de estado se definió utilizando YAKINDU Statechart Tools, que admite la generación de SCXML. Este SCXML se puede agregar al proyecto Qt y se puede editar en Qt Creator. Como puede ver en la fig. 2, la máquina de estado tiene la estructura idéntica a la de la fig. 1, pero algunos detalles, como las acciones de transición, no son visibles en Qt Creator. YAKINDU Statechart Tools ofrece algunas ventajas más, pero no las comentaré aquí.

Más importante aquí es el hecho de que YAKINDU Statechart Tools también puede generar clases de máquina de estado C ++ basadas en switch-case. También proporciona una opción para generar clases habilitadas para Qt con señales y ranuras, por lo que esto es útil. Con esta herramienta, solo tuve que implementar la máquina de estado basada en patrones de estado usando QStateMachine manualmente. No había ningún generador de código disponible para esa variante. Sin embargo, pude ahorrar mucho esfuerzo de implementación, mientras obtenía máquinas de estado semánticamente equivalentes para las pruebas de rendimiento con solo usar una única definición de diagrama de estado.

Todos los casos de prueba siguen el mismo esquema. Como quería medir el tiempo promedio necesario para procesar eventos individuales, cada prueba capturó un millón de iteraciones de un solo bucle de estado. Cada ciclo de estado realiza todos los eventos necesarios para visitar todos los estados y procesar todas las transiciones y acciones de transición. Entonces, un bucle de estado comienza y termina con el estado A estando activo. Esto significa que por cada caso de prueba 6 millones de en eventos y acciones de transición y 1 millón de salidas Se procesan los eventos con sus acciones de transición asociadas. Las pruebas se ejecutaron como una aplicación de línea de comandos y registraron el tiempo de las iteraciones como un solo lote. El consumo de tiempo por evento se puede determinar simplemente dividiendo el tiempo medido por la suma del número de en eventos y fuera eventos. Las pruebas se realizaron varias veces y se eligieron los resultados de medición con los valores más bajos.

Las pruebas se realizaron utilizando código optimizado sin información de depuración en mi antiguo MacBook Pro (mediados de 2014), con CPU Core i7 Quad Core a 2,4 GHz. Por supuesto, los números concretos diferirán en diferentes máquinas y sistemas operativos. Sin embargo, esto no es relevante, ya que quería comparar los diferentes enfoques de implementación entre sí. Estas diferencias relativas serán comparables en diferentes plataformas de hardware y sistema operativo.

Echemos un vistazo a las cifras de rendimiento

Sí, creo que casi todo el mundo habría esperado que una implementación simple de C ++ fuera más rápida que las otras alternativas, pero la magnitud de las diferencias es realmente asombrosa.


Figura 3:Comparación del tiempo de procesamiento de un solo evento. (Fuente:Autor)

Procesar eventos individuales usando C ++ simple tomó un promedio de 7 nanosegundos. El uso de SCXML requirió 33,850 nanosegundos, ¡eso es un factor de aproximadamente 4800 y una gran diferencia! A modo de comparación, la luz viaja más de 10 kilómetros mientras que la máquina de estado SCXML procesa solo una transición, mientras que la misma transición en la máquina de estado C ++ simple solo deja mucho tiempo para que la luz viaje un poco más de 2 metros. Esto implica órdenes de magnitud muy diferentes para los ciclos de la CPU y el consumo de energía.

Por supuesto, los números de hormigón dependen de la máquina y del procedimiento de prueba que se utilizó. Discutiré este tema más adelante. Pero analicemos primero los otros números. Los primeros tres escenarios de prueba incluyen todos una lógica de transición de estado idéntica, que fue generada por YAKINDU Statechart Tools, pero cada uno se envuelve de diferentes maneras.

El uso de señales y ranuras para manejar eventos tomó 72ns en promedio cuando se usaron conexiones directas. Entonces, este mecanismo impone una sobrecarga mínima de ~ 90%, en comparación con la lógica de la máquina de estado real. En este punto, no quiero argumentar que el uso de señales y ranuras ralentiza las aplicaciones. En su lugar, prefiero afirmar que las implementaciones de código simple de las máquinas de estado son extremadamente rápidas .

Al comparar esto con el tercer escenario, se obtiene una buena impresión de la sobrecarga de rendimiento causada por el uso de la cola de eventos. En este escenario, todos los eventos del diagrama de estado se enrutan a través de la cola de eventos. Con 731ns por evento, se necesita un factor de ~ 10 en comparación con las señales y ranuras y ~ 100 en comparación con C ++ simple.

Podemos suponer que una sobrecarga comparable también se aplica a los otros dos escenarios "simple QStateMachine ”Y“ máquina de estado SCXML ”:ambos requieren una cola de eventos activa. Entonces, cuando la sobrecarga de la cola de eventos supuesta se resta de los 5200ns por evento, obtenemos un consumo de tiempo aproximado de QStateMachine marco de 4500ns por evento. En comparación con el enfoque de código simple, las implementaciones de máquinas de estado basadas en QStateMachine son lentas. Este es un factor de aproximadamente 635, en comparación con la implementación del código C ++ simple.

Finalmente, echemos un vistazo al intérprete SCXML. Implica interpretar el código JavaScript y agrega otro factor de ~ 7. En comparación con el enfoque de código simple, las implementaciones de máquinas de estado basadas en SCXML son muy lentas.

¿Qué pasa con las máquinas de estado jerárquicas y ortogonales?

Hasta ahora, solo he perfilado una simple máquina de estado plano. Pero los gráficos de estado proporcionan muchas más características, y las dos características estructurales más importantes son la jerarquía y la ortogonalidad. Entonces, ¿qué impacto tiene el uso de estas características con respecto al tiempo de ejecución de la máquina de estado?

Primero, para medir el impacto de las jerarquías, definí una variante jerárquica de la máquina de estados a perfilar, que se muestra en la fig. 4.


Figura 4:Diagrama de estado de prueba jerárquico. (Fuente:Autor)

Proporciona exactamente el mismo comportamiento que la máquina de estado plano, pero agrega algunos estados compuestos. Mantener la funcionalidad idéntica, pero solo cambiar la estructura, permite averiguar cuánta sobrecarga implica la variante estructural, si corresponde.

En segundo lugar, para medir el impacto de la ortogonalidad, repliqué la máquina de estado plano en forma de cuatro regiones ortogonales. Todos tienen exactamente la misma funcionalidad. Entonces, la máquina de estado resultante (ver fig. 5) hará cuatro veces más trabajo que la máquina de estado simple.


Figura 5:Cuadro de estado de prueba ortogonal. (Fuente:Autor)

Para la creación de perfiles, elegí las implementaciones de C ++ simple y SCXML, porque eran las variantes más rápidas y más lentas. El diagrama de la fig. 6 muestra los resultados. Es muy alentador que el uso de jerarquías en los gráficos de estado no tenga ningún impacto medible en el rendimiento en ambas variantes de implementación.


Figura 6:Impacto en el desempeño de las jerarquías y la ortogonalidad. (Fuente:Autor)

Otro resultado positivo es que el uso de la ortogonalidad tampoco tiene ningún impacto negativo. Por el contrario, si bien uno podría haber esperado al menos cuatro veces el tiempo de procesamiento para lograr cuatro veces el trabajo, los aumentos efectivos en el tiempo de ejecución con factores ~ 2.4 y ~ 3.1 son significativamente menores que 4.

¿Por qué es este el caso? La razón de esto es que existe una parte general del procesamiento de la máquina de estados que es independiente del procesamiento de estados y eventos individuales. Esta parte toma el 52% (o 3.5ns por evento) para la máquina de estado C ++ simple, en comparación con el 28% (o 9300ns por evento) para SCXML. Finalmente, los estados ortogonales tienen menos impacto cuando se usa código C ++ generado en comparación con SCXML.

Conclusión

C ++ simple es mucho más eficiente que todas las alternativas. El uso de señales y ranuras o la cola de eventos Qt son mecanismos marco que facilitan la implementación y el mantenimiento de aplicaciones complejas de máquinas de estado. El marco de la máquina de estado Qt requiere ambos mecanismos. Con el código C ++ generado, tiene la opción.

En muchos escenarios, especialmente los interactivos, incluso las máquinas de estado SCXML son lo suficientemente rápidas y pueden proporcionar más flexibilidad al hacer que el comportamiento sea configurable al cambiar las definiciones de los diagramas de estado en tiempo de ejecución.


Incrustado

  1. Cómo elegir el mejor software CAD de diseño de joyas
  2. Las mejores marcas de CNC
  3. Cómo elegir la máquina CNC adecuada
  4. Cómo garantizar la preparación para emergencias en el almacén
  5. ¿Cómo monitorear el desempeño del personal técnico?
  6. Cómo elegir el mejor freno para aerogeneradores
  7. Cómo elegir la máquina estuchadora adecuada
  8. Cómo elegir la máquina de corte por chorro de agua adecuada
  9. Cómo elegir la mejor plegadora de chapa metálica
  10. ¿Cómo elegir la mejor bomba sumergible?
  11. La mejor dobladora:la dobladora de tubos eléctrica