Hi,
Well how about this then, I've reimplemented both the Java and the C++
version to be identical. They both use arrays and only brushes are
cached since it's not a good idea to new stuff during painting. Now I
get 20.7 fps in Java and 15.3 fps in c++ on my Ubuntu box running on a
Dell M90 laptop, thats about 35% faster in Java....
-=Børge
Gunnar Sletta wrote:
Børge Austvold wrote:
Hi,
I had some available time now before x-mas and did some tests on
OpenGL performance. I had a feeling for some reasons that writing
OpenGL applications in Java had be to slower that native ones in C++.
So, to test this I fired up an simple application that paints 10000
rectangles and 50 images with some opacity using a QPainter on a
QGLWidget. I wrote the same application in C++ using QT 4.4 and in
Java using Jambi 4.4. On the first run the java application stopped
every 5th second to garbage collect. When I removed all allocations
and cached some random calculations (in both c++ and java) the java
application is running 30% faster on my Dell M90 laptop running both
Linux Mint (Ubuntu 8.10) and Windows Vista. The linux version in java
(and c++) is also running significant faster than on Vista.
Did some more testing and It seems like the java version is always
faster than the c++ version. The only exception was when I tested
this on a KDE 4.1 machine. There the C++ version ran faster.... How
can this be possible? Is the HotSpot stuff from sun able to optimize
passed the JNI in the stack ?
Any thoughts on this ?
There are two reasons for the difference that I can see. The startup
time to get the pixmap loaded into graphics memory etc seems to be a
bit costly, so I reset the timer every 5 sec. Then I noticed that you
preincrement the counter in java and postincrement it in C++, meaning
that you will count one less frame in C++, and since the code is
running at 19 Fps (at least on my machine, this will affect the output).
The initialization of the data is also quite different and the speed
is dependent on how much of the pixels are being written and read and
speed is far more dependent on how much you're actually drawing than
on the runtime. If you sync up the implementations, the two will
perform pretty much identical.
best regards,
Gunnar
import com.trolltech.qt.QtBlockedSlot;
import com.trolltech.qt.core.QPoint;
import com.trolltech.qt.core.QSize;
import com.trolltech.qt.core.QTimer;
import com.trolltech.qt.gui.*;
import com.trolltech.qt.opengl.QGLWidget;
import java.util.Random;
/**
* @author Børge Austvold
*/
public class TestOpenGL extends QGLWidget {
private QTimer timer = new QTimer();
private QPixmap image = new QPixmap("../image.png");
private QPoint[] poses = new QPoint[50];
private Random random = new Random();
private long startTime = System.currentTimeMillis();
private int counter;
private QBrush[] brush = new QBrush[100];
private int brushPointer;
public TestOpenGL() {
timer.setInterval(0);
timer.setSingleShot(false);
timer.timeout.connect(this, "animate()");
for (int a = 0; a < poses.length; a++) {
poses[a] = new QPoint(0, 0);
}
for (int i = 0; i < brush.length; i++) {
brush[i] = new QBrush(new QColor(random.nextInt(255), random.nextInt(255), random.nextInt(255)));
}
timer.start();
}
public void animate() {
int w = width();
int h = height();
for (QPoint point : poses) {
int nx = point.x() + random.nextInt(10);
int ny = point.y() + random.nextInt(10);
point.setX(nx > w ? 0 : nx);
point.setY(ny > h ? 0 : ny);
}
update();
}
@QtBlockedSlot
protected void paintEvent(QPaintEvent arg__1) {
QPainter painter = new QPainter(this);
painter.setOpacity(0.3);
for (int a = 0; a < 10000; a++) {
if (++brushPointer == brush.length) {
brushPointer = 0;
}
painter.fillRect(random.nextInt(width()), random.nextInt(height()), 50, 50, brush[brushPointer]);
}
painter.setOpacity(0.5);
for (QPoint point : poses) {
painter.drawPixmap(point, image);
}
painter.drawText(100, 100, String.valueOf(++counter / ((System.currentTimeMillis() - startTime) / 1000.0)));
}
public static void main(String[] args) {
QApplication.initialize(args);
new TestOpenGL().showFullScreen();
QApplication.exec();
}
}
#include "widget.h"
#include <QPainter>
Widget::Widget()
: QGLWidget(), _counter( 0 )
{
_pixmap.load( "../image.png" );
connect( &_timer, SIGNAL( timeout() ), SLOT( animate() ) );
_timer.start(0);
for (int a = 0; a < 50; a++) {
_points[a].setX(0);
_points[a].setY(0);
}
for ( int i = 0; i < 100; ++i ) {
_brushes[i] = QBrush( QColor( rand() % 255, rand() % 255, rand() % 255 ) );
}
_time.start();
}
Widget::~Widget()
{
}
void Widget::animate() {
int w = width();
int h = height();
for(int a = 0; a < 50; a++){
int nx = _points[a].x() + rand() % 10;
int ny = _points[a].y() + rand() % 10;
_points[a].setX(nx > w ? 0 : nx);
_points[a].setY(ny > h ? 0 : ny);
}
update();
}
void Widget::paintEvent( QPaintEvent* e ) {
QPainter p( this );
int brushPointer = 0;
p.setOpacity( 0.3 );
for (int a = 0; a < 10000; a++) {
if (++brushPointer == 100 ) brushPointer = 0;
p.fillRect(rand() % width(), rand() % height(), 50, 50, _brushes[brushPointer]);
}
p.setOpacity( 0.5 );
for( int a = 0; a<50; a++){
p.drawPixmap(_points[a], _pixmap );
}
double fps = _counter++ / ( _time.elapsed() / 1000.0 );
p.drawText( 100, 100, QString::number( fps ) );
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QGLWidget>
#include <QList>
#include <QPixmap>
#include <QTimer>
#include <QTime>
class Widget : public QGLWidget
{
Q_OBJECT
public:
Widget();
~Widget();
protected:
void paintEvent( QPaintEvent* e );
private:
QPoint _points[50];
QBrush _brushes[100];
QPixmap _pixmap;
QTimer _timer;
int _counter;
QTime _time;
private slots:
void animate();
};
#endif // WIDGET_H
_______________________________________________
Qt-jambi-interest mailing list
[email protected]
http://lists.trolltech.com/mailman/listinfo/qt-jambi-interest