Measuring Qt Performance
I decided to continue the series of articles about the Aurora OS (until recently called Sailfish). During the time that I work with this OS, I have accumulated various observations that relate to the performance of applications on Qt and the system as a whole, because it is hung with a variety of devices, like a Christmas tree, I notice all the little things at startup. I think that this can be interesting and useful to colleagues who also work with Qt (or will work soon). Suggest that you can test more.
I program in Qt and often discuss with colleagues, iOS developers, the similarities, differences, and benefits of approaches. At some point, we still decided to move from words to deeds and take measurements. We did not find an Android programmer who was ready to participate in our entertainment, so a comparison with the participation of numbers and tables will be only for Swift and C ++.
I want to remind you that Qt / C ++ does not impose its memory management mechanism, and the user himself solves this issue within the framework of the capabilities available in C ++, while in Swift reference counting is used, and in Java it is a garbage collector. Thus, the programmer has the opportunity to interact with memory more efficiently. In order to send an http request or read data from a database, Qt relies on its own strengths, and does not use the ready-made frameworks that the OS provides. Exceptions - interaction with the keyboard, drawing the application start window, displaying notifications and other things.
First of all, we decided to write a simple algorithm (the sieve of Eratosthenes), run it on large numbers and compare the calculation time. Launched on iPhone 7.
Program on Swift:
I will not dwell on the code in detail, the linear Eratosthenes is not obvious to understanding, especially if one of the languages is not familiar to you. Here is a link with a description: https://e-maxx.ru/algo/prime_sieve_linear , who are interested, can check for honesty. By the way, the swift version turned out to be a little more optimized in the little things (you can look for them), which did not prevent the plus version from winning the performance.
Qt program:
Run the program. Applications have a field for entering the number n, a start button and a field with the total time:
Swift - on the left, Qt - on the right.
Result. Here is a table of measurements for different n and at different points in time:
As you can see, a C ++ application is ~ 1.5 times faster than the native one with identical algorithms.
Naturally, computing in the context of mobile applications is an important thing, but far from the only one. Therefore, we drew a ListView consisting of 1000 elements, each of which contains text and a picture, in order to look at the speed of rendering graphic elements. Below, in the videos, you can see the result:
Qt:
Swift:
Visually, the difference is not noticeable.
In the Sailfish OS, we have a Linux kernel and a graphical native shell on Qt, and this in itself suggests thoughts about the good performance of this OS. I often notice that the Inoi R7 wins in terms of the speed of some tasks, although the Samsung Galaxy S8 does the same. So, for example, the Samsung Galaxy S8 sends, receives, processes, packs into a database, etc. 10K http requests in about 3-4 minutes, and Inoi R7 does the same thing for 5-6 minutes. Given the difference in iron performance, the result is impressive.
For a more honest test of OS performance, I decided to look at the response speed of the wheelbarrow.
Simple and unpretentious. I don’t have a phone that supports Sailfish and Android for personal use, so I had to look at my colleagues for a phone that is as close as possible to Inoi r7, but on Android. Which suddenly turned out to be very difficult, considering that I am sitting in a mobile development office.
Sony Xperia Z5 compact:
Processor - Qualcomm Snapdragon 810 MSM8994, 2000 MHz
Number of processor cores - 8
Video processor - Adreno 430
Internal memory - 32 GB
RAM - 2 GB
Inoi R7:
Processor - Qualcomm Snapdragon 212 MSM8909AA, 1200 MHz
Number of processor cores - 4
Video processor - Adreno 304
Internal memory - 16 GB
RAM - 2 GB
Sony nevertheless turned out to be more powerful, but for the odds equation we turn on the power saving mode on it, all the same it will not lead to the complete equality of the power of the devices. On the video you can see that on Android the line is not as smooth as on Sailfish.
Left - Sony, right - Inoi:
I don’t argue, this is not a very serious indicator, you need to compare not only the capabilities of a pure language, but also different libraries, native and cross-platform, to compare their performance and ease of use, because there are very few applications that use only ListView and the Eratosthenes sieve. Although all these little things together look very convincing to me.
Of course, everything is not so rosy with Qt, as I try to paint here, there are cons. For example, working with TextInput on Android, you can torture perfectionists who are especially sensitive to crutches, because on each device Qt manages to put absolutely unique sticks in the wheels when interacting with the keyboard. On one phone, the picture goes up, on the other it stands still, but EnterKey does not work, on the third, only uppercase letters are always entered, and there is no way to convince it to switch to lowercase. You can go on ad infinitum. And all this also slows down! (Grunts are relevant only for Android, there are no such problems on Sailfish, everything works fine). In addition, on Qt it is difficult to achieve the native appearance of the application.
The main conclusion that can be drawn: Qt, being a cross-platform tool, is not inferior in performance to native development tools. It is perfect for programs in which, in addition to the GUI, there is still a lot of mathematics, and especially for enterprise applications, where there are many nuances and few employees, so as not to create an independent version for each OS. Functions are more important for corporate users than native UI. For Aurora, Qt is a native tool for application development, which probably gives some other performance boost.
It would be interesting to test the Aurora on a powerful hardware like my Galaxy S8.
I program in Qt and often discuss with colleagues, iOS developers, the similarities, differences, and benefits of approaches. At some point, we still decided to move from words to deeds and take measurements. We did not find an Android programmer who was ready to participate in our entertainment, so a comparison with the participation of numbers and tables will be only for Swift and C ++.
I want to remind you that Qt / C ++ does not impose its memory management mechanism, and the user himself solves this issue within the framework of the capabilities available in C ++, while in Swift reference counting is used, and in Java it is a garbage collector. Thus, the programmer has the opportunity to interact with memory more efficiently. In order to send an http request or read data from a database, Qt relies on its own strengths, and does not use the ready-made frameworks that the OS provides. Exceptions - interaction with the keyboard, drawing the application start window, displaying notifications and other things.
Test 1
First of all, we decided to write a simple algorithm (the sieve of Eratosthenes), run it on large numbers and compare the calculation time. Launched on iPhone 7.
Program on 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
public init(upTo limit: Int) {
self.iterator = AnyIterator(EratosthenesIterator(upTo: limit))
}
public func makeIterator() -> AnyIterator {
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
}
}
I will not dwell on the code in detail, the linear Eratosthenes is not obvious to understanding, especially if one of the languages is not familiar to you. Here is a link with a description: https://e-maxx.ru/algo/prime_sieve_linear , who are interested, can check for honesty. By the way, the swift version turned out to be a little more optimized in the little things (you can look for them), which did not prevent the plus version from winning the performance.
Qt program:
#include "eratosthenes.h"
#include
#include
#include
#include
#include
#include
#include
Eratosthenes::Eratosthenes(QObject *parent)
{
time = 0;
}
void Eratosthenes::qtFunction(int n)
{
clock_t start, end;
start = clock();
std::vector lp = std::vector(n + 1, 0);
std::vector 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;
}
Run the program. Applications have a field for entering the number n, a start button and a field with the total time:
Swift - on the left, Qt - on the right.
Result. Here is a table of measurements for different n and at different points in time:
As you can see, a C ++ application is ~ 1.5 times faster than the native one with identical algorithms.
Test 2
Naturally, computing in the context of mobile applications is an important thing, but far from the only one. Therefore, we drew a ListView consisting of 1000 elements, each of which contains text and a picture, in order to look at the speed of rendering graphic elements. Below, in the videos, you can see the result:
Qt:
Swift:
Visually, the difference is not noticeable.
Test 3
In the Sailfish OS, we have a Linux kernel and a graphical native shell on Qt, and this in itself suggests thoughts about the good performance of this OS. I often notice that the Inoi R7 wins in terms of the speed of some tasks, although the Samsung Galaxy S8 does the same. So, for example, the Samsung Galaxy S8 sends, receives, processes, packs into a database, etc. 10K http requests in about 3-4 minutes, and Inoi R7 does the same thing for 5-6 minutes. Given the difference in iron performance, the result is impressive.
For a more honest test of OS performance, I decided to look at the response speed of the wheelbarrow.
Test.cpp:
#include "mypainter.h"
#include
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 and unpretentious. I don’t have a phone that supports Sailfish and Android for personal use, so I had to look at my colleagues for a phone that is as close as possible to Inoi r7, but on Android. Which suddenly turned out to be very difficult, considering that I am sitting in a mobile development office.
Sony Xperia Z5 compact:
Processor - Qualcomm Snapdragon 810 MSM8994, 2000 MHz
Number of processor cores - 8
Video processor - Adreno 430
Internal memory - 32 GB
RAM - 2 GB
Inoi R7:
Processor - Qualcomm Snapdragon 212 MSM8909AA, 1200 MHz
Number of processor cores - 4
Video processor - Adreno 304
Internal memory - 16 GB
RAM - 2 GB
Sony nevertheless turned out to be more powerful, but for the odds equation we turn on the power saving mode on it, all the same it will not lead to the complete equality of the power of the devices. On the video you can see that on Android the line is not as smooth as on Sailfish.
Left - Sony, right - Inoi:
I don’t argue, this is not a very serious indicator, you need to compare not only the capabilities of a pure language, but also different libraries, native and cross-platform, to compare their performance and ease of use, because there are very few applications that use only ListView and the Eratosthenes sieve. Although all these little things together look very convincing to me.
Minuses
Of course, everything is not so rosy with Qt, as I try to paint here, there are cons. For example, working with TextInput on Android, you can torture perfectionists who are especially sensitive to crutches, because on each device Qt manages to put absolutely unique sticks in the wheels when interacting with the keyboard. On one phone, the picture goes up, on the other it stands still, but EnterKey does not work, on the third, only uppercase letters are always entered, and there is no way to convince it to switch to lowercase. You can go on ad infinitum. And all this also slows down! (Grunts are relevant only for Android, there are no such problems on Sailfish, everything works fine). In addition, on Qt it is difficult to achieve the native appearance of the application.
Conclusion
The main conclusion that can be drawn: Qt, being a cross-platform tool, is not inferior in performance to native development tools. It is perfect for programs in which, in addition to the GUI, there is still a lot of mathematics, and especially for enterprise applications, where there are many nuances and few employees, so as not to create an independent version for each OS. Functions are more important for corporate users than native UI. For Aurora, Qt is a native tool for application development, which probably gives some other performance boost.
It would be interesting to test the Aurora on a powerful hardware like my Galaxy S8.