May 22, 2015

Qt: Reading text files with or without QTextStream?

The question: Qt offers two ways to read text files. You always have to open the file using QFile, but then you can either use a QTextStream on the file or not. The most obvious difference is that the QTextStream returns the lines as QString, whereas QFile returns QByteArrays. QByteArrays should be faster - but how much? The documentation does not say anything about the performance. Thus, I compared the approaches and also evaluated the influence of where the line variable is declared - before the loop or inside the loop:

The code: Here is the code for the benchmark. It creates text files with 100000 lines of length 100 to 1000. Then it reads each file 10 times with each method:
   
 QTextStream(stdout) << "#line_length\t0 (file_array_outside)\t1 (file_array_inside)\t2 (file_string_outside)\t3 (file_string_inside)\t4 (stream_string_outside)\t5 (stream_string_inside)";  
 for (int ll=100; ll<1001; ll+=100)  
 {  
     QString output = QString::number(ll);  
    
     //create file to load  
     QFile data("input.txt");  
     data.open(QFile::WriteOnly);  
     QTextStream out(&data);  
     {  
         for (int i=0; i<100000; ++i)  
         {  
             out << QString(ll, 'c') << endl;  
         }  
     }  
     data.close();  
    
     //load  
     for (int mode=0; mode<6; ++mode)  
     {  
         long size = 0;  
         QTime timer;  
         timer.start();  
         for (int i=0; i<10; ++i)  
         {  
             QFile in("input.txt");  
             in.open(QFile::ReadOnly | QFile::Text);  
    
             switch (mode)  
             {  
                 case 0:  
                 {  
                    QByteArray line;  
                    while(!in.atEnd())  
                    {  
                        line = in.readLine();  
                        size += line.length();  
                    }  
                 }  
                 case 1:  
                 {  
                    while(!in.atEnd())  
                    {  
                        QByteArray line = in.readLine();  
                        size += line.length();  
                    }  
                 }  
                 case 2:  
                 {  
                    QString line;  
                    while(!in.atEnd())  
                    {  
                        line = in.readLine();  
                        size += line.length();  
                    }  
                 }  
                 case 3:  
                 {  
                    while(!in.atEnd())  
                    {  
                        QString line = in.readLine();  
                        size += line.length();  
                    }  
                 }  
                 case 4:  
                 {  
                    QTextStream stream(&in);  
                    QString line;  
                    while(!stream.atEnd())  
                    {  
                        line = stream.readLine();  
                        size += line.length();  
                    }  
                 }  
                 case 5:  
                 {  
                    QTextStream stream(&in);  
                    while(!stream.atEnd())  
                    {  
                        QString line = stream.readLine();  
                        size += line.length();  
                    }  
                 }  
             }  
             in.close();  
         }  
         output += "\t" + QString::number(timer.elapsed());  
     }  
     QTextStream(stdout) << output;  
 }  

The result:

The benchmark results in milliseconds for Windows 7, Qt 5.1.1, MinGW 4.8.0 are:
line file array_outsidefile array_insidefile string_outsidefile string_insidestream string_outsidestream string_inside
100
1003
855
1315
1337
2198
2252
200
4735
991
1720
1793
4118
4107
300
4866
1144
2141
2258
6064
6060
400
5218
1456
2560
2584
8012
8039
500
5411
1479
3077
3244
10585
10426
600
5770
1697
3614
3697
12127
12119
700
6005
1857
3976
4026
14097
14010
800
6529
2070
4504
4509
16310
16143
900
6310
2261
4926
5061
18308
18268
1000
6851
2521
5560
5454
20427
20226

The benchmark results in milliseconds for Ubuntu 12.04 7, Qt 5.1.0, GCC 4.6.3 are:
linefile array_outsidefile array_insidefile string_outsidefile string_insidestream string_outsidestream string_inside
100
481
384
857
880
815
814
200
561
467
1436
1216
1489
1487
300
612
540
1873
1560
2206
2200
400
707
599
2309
1866
2780
2771
500
732
655
2696
2231
3416
3408
600
843
740
3171
2629
4104
4071
700
1371
824
3597
2963
4750
4743
800
1100
930
4063
3361
5567
5954
900
1324
1034
4514
3742
6242
6649
1000
1254
1150
4973
4136
7040
7381

The conclusion:
Reading text files with QFile alone is much faster than with QTextStream. Using QByteArray for the line variable further speeds up reading the file. The line variable should be declared inside the loop because it speeds up the calculation, at least under Linux.

No comments:

Post a Comment