Medición del rendimiento de Qt

Decidí continuar la serie de artículos sobre Aurora OS (hasta hace poco llamado Sailfish). Durante el tiempo que trabajo con este sistema operativo, he acumulado varias observaciones relacionadas con el rendimiento de las aplicaciones en Qt y el sistema en su conjunto, ya que está colgado con una variedad de dispositivos, como un árbol de Navidad, noto todas las pequeñas cosas al inicio. Creo que esto puede ser interesante y útil para los colegas que también trabajan con Qt (o lo harán pronto). Sugiere que puedas probar más.



Programa en Qt y a menudo discuto con colegas, desarrolladores de iOS, las similitudes, diferencias y beneficios de los enfoques. En algún momento, aún decidimos pasar de las palabras a los hechos y tomar medidas. No encontramos un programador de Android que estuviera listo para participar en nuestro entretenimiento, por lo que una comparación con la participación de números y tablas será solo para Swift y C ++.

Quiero recordarle que Qt / C ++ no impone su mecanismo de administración de memoria, y el usuario mismo resuelve este problema dentro del marco de las capacidades disponibles en C ++, mientras que en Swift se usa el conteo de referencias, y en Java es un recolector de basura. Por lo tanto, el programador tiene la oportunidad de interactuar con la memoria de manera más eficiente. Para enviar una solicitud http o leer datos de una base de datos, Qt se basa en sus propios puntos fuertes y no utiliza los marcos ya preparados que proporciona el sistema operativo. Excepciones: interacción con el teclado, dibujar la ventana de inicio de la aplicación, mostrar notificaciones y otras cosas.

Prueba 1


En primer lugar, decidimos escribir un algoritmo simple (el tamiz de Eratóstenes), ejecutarlo en grandes cantidades y comparar el tiempo de cálculo. Lanzado en iPhone 7.

Programa Swift:

swift // // ViewController.swift // Eratosthenes // // Created by Dmitry Shadrin on 22/11/2018. // Copyright 2018 Digital Design. All rights reserved. // import UIKit class ViewController: UIViewController { @IBOutlet weak var digitTextField: UITextField! @IBOutlet weak var timeLabel: UILabel! @IBAction func startAction(_ sender: UIButton) { guard let text = digitTextField.text, let number = Int(text) else { return } prime(n: number) } func prime(n: Int) { let startTime = DispatchTime.now() let _ = PrimeSequence(upTo: n) .reduce(into: [], { $0.append($1) }) //      let endTime = DispatchTime.now() let time = (endTime.uptimeNanoseconds - startTime.uptimeNanoseconds) timeLabel.text = "\(time)" } } public struct PrimeSequence: Sequence { private let iterator: AnyIterator<Int> public init(upTo limit: Int) { self.iterator = AnyIterator(EratosthenesIterator(upTo: limit)) } public func makeIterator() -> AnyIterator<Int> { return iterator } } private struct EratosthenesIterator: IteratorProtocol { let n: Int var composite: [Bool] var current = 2 init(upTo n: Int) { self.n = n self.composite = [Bool](repeating: false, count: n + 1) } mutating func next() -> Int? { while current <= self.n { if !composite[current] { let prime = current for multiple in stride(from: current * current, through: self.n, by: current) { composite[multiple] = true } current += 1 return prime } current += 1 } return nil } } 


No me detendré en el código en detalle, el Eratóstenes lineal no es obvio de entender, especialmente si uno de los idiomas no le es familiar. Aquí hay un enlace con una descripción: https://e-maxx.ru/algo/prime_sieve_linear , quienes estén interesados, pueden verificar la honestidad. Por cierto, la versión rápida resultó estar un poco más optimizada en detalles (puede buscarlos), lo que no impidió que la versión plus ganara el rendimiento.

Programa Qt:
 #include "eratosthenes.h" #include <stdio.h> #include <stdlib.h> #include <time.h> #include <QVector> #include <QDebug> #include <vector> #include <cmath> Eratosthenes::Eratosthenes(QObject *parent) { time = 0; } void Eratosthenes::qtFunction(int n) { clock_t start, end; start = clock(); std::vector<int> lp = std::vector<int>(n + 1, 0); std::vector<int> pr; //       pr.reserve(std::sqrt(n) / 2); for (int i = 2; i <= n; ++i) { if (lp[i] == 0) { lp[i] = i; pr.emplace_back(i); } for (int j = 0; j < pr.size() && pr[j] <= lp[i] && i * pr[j] <= n; ++j) { lp[i * pr[j]] = pr[j]; } } end = clock(); time = (end - start) / (double)CLOCKS_PER_SEC; pTimeChanged(); qDebug() << "  " << pr.size() << "" << time; } 

Ejecute el programa Las aplicaciones tienen un campo para ingresar el número n, un botón de inicio y un campo con un tiempo total:


Swift - a la izquierda, Qt - a la derecha.

Resultado Daré una tabla de medidas para diferentes ny en diferentes momentos:

Como puede ver, una aplicación C ++ es ~ 1.5 veces más rápida que una nativa con algoritmos idénticos.

Prueba 2


Naturalmente, la informática en el contexto de las aplicaciones móviles es algo importante, pero lejos de ser la única. Por lo tanto, dibujamos un ListView que consta de 1000 elementos, cada uno de los cuales contiene texto y una imagen, para ver la velocidad de representación de elementos gráficos. A continuación, en los videos, puede ver el resultado:

Qt:

Rápido:


Visualmente, la diferencia no es notable.

Prueba 3


En el sistema operativo Sailfish, tenemos un kernel de Linux y un shell nativo gráfico en Qt, y esto en sí mismo lleva a pensar en el buen rendimiento de este sistema operativo. A menudo noto que el Inoi R7 gana en términos de la velocidad de algunas tareas, aunque el Samsung Galaxy S8 hace lo mismo. Entonces, por ejemplo, el Samsung Galaxy S8 envía, recibe, procesa, empaqueta en una base de datos, etc. 10K solicitudes http en unos 3-4 minutos, e Inoi R7 hace lo mismo durante 5-6 minutos. Dada la diferencia en el rendimiento del hierro, el resultado es impresionante.

Para una prueba más honesta del rendimiento del sistema operativo, decidí mirar la velocidad de respuesta de la carretilla.

Test.cpp:


 #include "mypainter.h" #include <QPainter> MyPainter::MyPainter(QQuickItem *parent) : QQuickPaintedItem(parent) { } void MyPainter::paint(QPainter *painter) { QPen pen; pen.setWidth(10); pen.setColor(Qt::red); painter->setPen(pen); painter->drawPolyline(pol); } void MyPainter::xyCanged(int x, int y) { pol.append(QPoint(x, y)); update(); } 

Test.qml:


 import QtQuick 2.9 import QtQuick.Window 2.2 import Painter 1.0 Window { visible: true Painter { id: painter anchors.fill: parent MouseArea { anchors.fill: parent onPressed: { painter.xyCanged(mouseX, mouseY) } onMouseXChanged: { painter.xyCanged(mouseX, mouseY) } onMouseYChanged: { painter.xyCanged(mouseX, mouseY) } } } } 

Simple y sin pretensiones. No tengo un teléfono que sea compatible con Sailfish y Android para uso personal, así que tuve que mirar a mis colegas por un teléfono que esté lo más cerca posible de Inoi r7, pero en Android. Lo que de repente resultó ser muy difícil, teniendo en cuenta que estoy sentado en una oficina de desarrollo móvil.

Sony Xperia Z5 compact:
Procesador - Qualcomm Snapdragon 810 MSM8994, 2000 MHz
El número de núcleos de procesador: 8
Procesador de video - Adreno 430
La cantidad de memoria interna - 32 GB
La cantidad de RAM - 2 GB

Inoi R7:
Procesador - Qualcomm Snapdragon 212 MSM8909AA, 1200 MHz
El número de núcleos de procesador: 4
Procesador de video - Adreno 304
La cantidad de memoria interna - 16 GB
La cantidad de RAM - 2 GB

Sin embargo, Sony resultó ser más potente, pero para la ecuación de probabilidades activamos el modo de ahorro de energía, de todos modos no conducirá a la igualdad completa de la potencia de los dispositivos. En el video puedes ver que en Android la línea no es tan fluida como en Sailfish.

Izquierda - Sony, derecha - Inoi:



No discuto, este no es un indicador muy serio, necesita comparar no solo las capacidades de un lenguaje puro, sino también diferentes bibliotecas, nativas y multiplataforma, para comparar su rendimiento y facilidad de uso, porque hay muy pocas aplicaciones que usan solo ListView y el tamiz Eratosthenes. Aunque todas estas pequeñas cosas juntas me parecen muy convincentes.

Contras


Por supuesto, todo no es tan optimista con Qt, ya que trato de pintar aquí, hay inconvenientes. Por ejemplo, al trabajar con TextInput en Android, puede torturar a los perfeccionistas que son especialmente sensibles a las muletas, porque en cada dispositivo Qt logra colocar palos absolutamente únicos en las ruedas cuando interactúa con el teclado. En un teléfono, la imagen sube, en el otro se detiene, pero EnterKey no funciona, en el tercero solo se ingresan letras mayúsculas y no hay forma de convencerlo de que cambie a minúsculas. Puedes ir ad infinitum. ¡Y todo esto también se ralentiza! (Los gruñidos son relevantes solo para Android, no hay tales problemas en Sailfish, todo funciona bien). Además, en Qt es difícil lograr la apariencia nativa de la aplicación.

Conclusión


La principal conclusión que se puede extraer: Qt, al ser una herramienta multiplataforma, no es inferior en rendimiento a las herramientas de desarrollo nativas. Es perfecto para programas en los que, además de la interfaz gráfica de usuario, todavía hay muchas matemáticas, y especialmente para aplicaciones empresariales, donde hay muchos matices y pocos empleados, para no crear una versión independiente para cada sistema operativo. Las funciones son más importantes para los usuarios corporativos que la IU nativa. Para Aurora, Qt es una herramienta nativa para el desarrollo de aplicaciones, que probablemente brinda algún otro impulso de rendimiento.

Sería interesante probar el Aurora en un hardware potente como mi Galaxy S8.

Source: https://habr.com/ru/post/457622/


All Articles