Parser for STL stereolithography data files I'm parsing STL files to load the coordinates. My code is:

void Importer::scanFileSTL_ASCII(
    QVector&lt;QVector3D&gt; &amp;vertices, // Coordinates to be filled 
    const QUrl &amp;url)
{
    QFile file;
    file.setFileName(url.toLocalFile());
    if (!file.open(QIODevice::OpenModeFlag::ReadOnly | QIODevice::OpenModeFlag::Text))
        return;

    while (!file.atEnd()) {
        QByteArray line_BA = file.readLine();
        QString line = QString::fromLatin1(line_BA);
        // Split line by spaces
        QStringList words = line.split(QRegExp("\\s+"), QString::SkipEmptyParts);
        if (words.isEmpty())
            continue; // Skip this line and jump to next iteration/line
        if (words[0] == "vertex") {
            assert (words.length() == 4 &amp;&amp; "STL file format is wrong: vertex-line must have 4 strings");
            float x = words[1].toFloat();
            float y = words[2].toFloat();
            float z = words[3].toFloat();
            vertices.append(QVector3D(x, y, z));
        }
    }

    return;
}


The code is tested, it works fine. But it is by far slower than the STL loader of asset import library. More accurate comparisons in release mode:

Import of a 13MB ASCII STL file: 


Assimp library: 03.58 seconds
Our code: 04.70 seconds


Import of 287MB ASCII STL file:


Assimp library: 05.72 seconds
Our code: 44.19 seconds


I wonder if something is noticeably wrong with my code. Thanks.
Well, it's not much of a mystery.  Your code is simple and pretty. Their code is ugly because it performs exactly what it needs to do, and no more:


} else if (!strncmp(sz,"vertex",6) &amp;&amp; ::IsSpaceOrNewLine(*(sz+6))) { // vertex 1.50000 1.50000 0.00000
    if (faceVertexCounter &gt;= 3) {
        ASSIMP_LOG_ERROR("STL: a facet with more than 3 vertices has been found");
        ++sz;
    } else {
        if (sz[6] == '\0') {
            throw DeadlyImportError("STL: unexpected EOF while parsing facet");
        }
        sz += 7;
        SkipSpaces(&amp;sz);
        positionBuffer.push_back(aiVector3D());
        aiVector3D* vn = &amp;positionBuffer.back();
        sz = fast_atoreal_move&lt;ai_real&gt;(sz, (ai_real&amp;)vn-&gt;x );
        SkipSpaces(&amp;sz);
        sz = fast_atoreal_move&lt;ai_real&gt;(sz, (ai_real&amp;)vn-&gt;y );
        SkipSpaces(&amp;sz);
        sz = fast_atoreal_move&lt;ai_real&gt;(sz, (ai_real&amp;)vn-&gt;z );
        faceVertexCounter++;
    }



A few differences in the amount of work it does:


There's no regex that needs to be compiled.
It's not splitting tokens into a list.  So, no list needs to be allocated and filled.  More importantly, no strings need to be allocated, copied, and destroyed.
The aiVector3D is allocated first, then each of the three numbers is parsed and written directly into the memory location of the coordinate, with no temporary variable assignments.


I'll also point out that your use of assert is improper.  You should only assert conditions that you know must be true due to logic.  You should not assert conditions that you hope to be true about the input.  If you compile with assertions disabled, then the validation code goes away!  That would introduce a bug, and possibly a security vulnerability.