Something really inefficient going on here

Discuss anything related to product development
Post Reply
seasoned_geek
Posts: 246
Joined: Thu Jun 11 2020 12:18 pm

Something really inefficient going on here

Post by seasoned_geek »

All,

There is something inefficient going on with memory management.

Code: Select all

/**
 * @brief Creates tokens from a single GDB output row.
 */
QList<Token *> GdbCom::tokenize( QString str )
{
    enum { IDLE, END_CODE, STRING, VAR} state = IDLE;
    QList<Token *> list;
    Token *cur = nullptr;
    bool prevCharIsEscCode = false;

    QDateTime now = QDateTime::currentDateTime();
    qDebug() << "***** tokenize() called at " << now.toString( "yyyyMMdd-hhmmss.zzz" ) << "  for '"
             << str << "'\n";


    if ( str.isEmpty() )
    {
        return list;
    }

    for ( int i = 0; i < str.size(); i++ )
    {
        QChar c = str[i];
        bool isEscaped = false;

        if ( c == '\\' && prevCharIsEscCode )
        {
            prevCharIsEscCode = false;
        }
        else if ( prevCharIsEscCode )
        {
            isEscaped = true;
            prevCharIsEscCode = false;
        }
        else if ( c == '\\' )
        {
            prevCharIsEscCode = true;
            continue;
        }

        switch ( state )
        {
            case IDLE:
            {
                if ( c == '"' )
                {
                    cur = new Token( Token::C_STRING );
                    list.push_back( cur );
                    state = STRING;
                }
                else if ( c == '(' )
                {
                    cur = new Token( Token::END_CODE );
                    list.push_back( cur );
                    cur->m_text += c;
                    state = END_CODE;
                }
                else if ( c == '=' || c == '{' || c == '}' || c == ',' ||
                          c == '[' || c == ']' || c == '+' || c == '^' ||
                          c == '~' || c == '@' || c == '&' || c == '*' )
                {
                    Token::Type type = Token::UNKNOWN;

                    if ( c == '=' )
                    {
                        type = Token::KEY_EQUAL;
                    }

                    if ( c == '{' )
                    {
                        type = Token::KEY_LEFT_BRACE;
                    }

                    if ( c == '}' )
                    {
                        type = Token::KEY_RIGHT_BRACE;
                    }

                    if ( c == '[' )
                    {
                        type = Token::KEY_LEFT_BAR;
                    }

                    if ( c == ']' )
                    {
                        type = Token::KEY_RIGHT_BAR;
                    }

                    if ( c == ',' )
                    {
                        type = Token::KEY_COMMA;
                    }

                    if ( c == '^' )
                    {
                        type = Token::KEY_UP;
                    }

                    if ( c == '+' )
                    {
                        type = Token::KEY_PLUS;
                    }

                    if ( c == '~' )
                    {
                        type = Token::KEY_TILDE;
                    }

                    if ( c == '@' )
                    {
                        type = Token::KEY_SNABEL;
                    }

                    if ( c == '&' )
                    {
                        type = Token::KEY_AND;
                    }

                    if ( c == '*' )
                    {
                        type = Token::KEY_STAR;
                    }

                    cur = new Token( type );
                    list.push_back( cur );
                    cur->m_text += c;
                    state = IDLE;
                }
                else if ( c != ' ' )
                {
                    cur = new Token( Token::VAR );
                    list.push_back( cur );
                    cur->m_text = c;
                    state = VAR;
                }

            };

            break;
            case END_CODE:
            {
                QString codeEndStr = "(gdb)";
                cur->m_text += c;

                if ( cur->m_text.length() == codeEndStr.length() )
                {
                    state = IDLE;

                }
                else if ( cur->m_text.compare( codeEndStr.left( cur->m_text.length() ) ) != 0 )
                {
                    cur->setType( Token::VAR );
                    state = IDLE;
                }

            };

            break;
            case STRING:
            {
                if ( c == '"' && isEscaped == false )
                {
                    state = IDLE;
                }
                else if ( isEscaped )
                {
                    if ( c == 'n' )
                    {
                        cur->m_text += '\n';
                    }
                    else if ( c == 't' )
                    {
                        cur->m_text += '\t';
                    }
                    else
                    {
                        cur->m_text += c;
                    }
                }
                else
                {
                    cur->m_text += c;
                }
            };

            break;
            case VAR:
            {
                if ( c == '=' || c == ',' || c == '{' || c == '}' )
                {
                    i--;
                    cur->m_text = cur->m_text.trimmed();
                    state = IDLE;
                }
                else
                {
                    cur->m_text += c;
                }
            };

            break;

        }

    }

    if ( cur )
    {
        if ( cur->getType() == Token::VAR )
        {
            cur->m_text = cur->m_text.trimmed();
        }
    }

    now = QDateTime::currentDateTime();
    qDebug() << "**** tokenize() completed at " << now.toString( "yyyyMMdd-hhmmss.zzz" ) << "\n";

    return list;
}
Yes, the code looks like he tried to stuff Qt into his C code. I'm looking past that for now because I think this performance issue is biting Diamond and many other applications.

You probably want to see Token too though it isn't much.

Code: Select all

class Token
{
public:

    enum Type
    {
        UNKNOWN,
        C_STRING,         // "string"
        C_CHAR,           // 'c'
        KEY_EQUAL,        // '='
        KEY_LEFT_BRACE,   // '{'
        KEY_RIGHT_BRACE,  // '}'
        KEY_LEFT_BAR,     // '['
        KEY_RIGHT_BAR,    // ']'
        KEY_UP,           // '^'
        KEY_PLUS,         // '-'
        KEY_COMMA,        // ','
        KEY_TILDE,        // '~'
        KEY_SNABEL,       // '@'
        KEY_STAR,         // '*'
        KEY_AND,          // '&'
        END_CODE,
        VAR
    };
public:

    Token( Type type ) : m_type( type ) {};

    static const QString &typeToString( Type type );
    Type getType() const
    {
        return m_type;
    };
    void setType( Type type )
    {
        m_type = type;
    };
    QString getString() const
    {
        return m_text;
    };

    const QString toString();

private:
    Type m_type;
public:
    QString m_text;
};
When run in Gede compiled with Qt.
Well under a second

When run in RedBug (my port) compiled in CopperSpice
Takes way too long

[ Edited for content and clarity ]
Post Reply