Decoding an element list

Posted on

Problem

I have a function which I am calling an infinite number of times (or until a condition is met). The problem with this recursive function is that on a higher level, it is called by a worker thread which pushes and pops to a deque. In the meantime, I am iterating through a file with the main thread which is a lot quicker than the recursive function which is processing data that is retrieved from iterating through that main loop.

An example of the code which is severely slowing things down is below:

bool CCapsule::DecodeElementList( ElementList &elementList, char* pszBuffer, unsigned int uiBufferLength, std::string strSrcAddress, std::string strDestAddress, std::vector<std::string> &vsContents, bool bIsInner )
{
    // Create an buffer to contain pszBuffer.
    RBuffer rBuffer;
    rBuffer.data = pszBuffer;

    // Create an RElement List and Element Entry to store elements
    RRet rRet;

    RElementEntry rElementEntry;

    // Decode Element List
    if(rDecodeElementList(&m_rDecodeIter, &rElementList, 0) >= RET_SUCCESS)
    {
        std::vector<std::string> _vsContents;
        while ((RRet = rDecodeElementEntry(&m_rDecodeIter, &rElementEntry)) != RRET_END_OF_CONTAINER)
        {
            if (RRet < RET_SUCCESS)
            {
                return false;
            }

            std::string strEntryName = "";

            if (rElementEntry.data != NULL)
                rElementEntry.data;

            switch(rElementEntry.dataType)
            {
            case R_MSG:
                // Create a new RCapsule to encapsulate the inner message.
                m_pInnerMessage = new CCapsule();
                if ( false == m_pInnerMessage->Load( pszBuffer, uiBufferLength, strSrcAddress, strDestAddress, _vsContents, true ) )
                {
                    // An error occurred, clean up.
                    delete m_pInnerMessage;
                    m_pInnerMessage = 0;
                    return false;
                }
                break;
            case R_ELEMENT_LIST:
                // Decode Element List
                RElementList rInnerElementList;
                DecodeElementList(rInnerElementList, pszBuffer, uiBufferLength, strSrcAddress, strDestAddress, _vsContents, true);
                break;
            case R_FIELD_LIST:
                // Decode Field List
                DecodeFieldList(pszBuffer, uiBufferLength);
                break;
            case R_DATE:
                {
                    // Decode DATE
                    RDate rDate;
                    RRet = rDecodeDate( &m_rDecodeIter, &rDate );
                    if ( RRet != RET_SUCCESS )
                    {
                        return false;
                    }
                    std::stringstream sstream;
                    sstream << static_cast<int>( rDate.day ) << "/" << static_cast<int>( rDate.month ) << "/" << rDate.year;
                    _vsContents.push_back(sstream.str());
                }
                break;
            case R_DATETIME:
                {
                    // Decode DATETIME
                    RDateTime rDateTime;
                    RRet = rDecodeDateTime( &m_rDecodeIter, &rDateTime );
                    if ( RRet != RET_SUCCESS )
                    {
                        return false;
                    }

                    RBuffer rStringBuffer;
                    RRet = rDateTimeToString( &rStringBuffer, R_DATETIME,  &rDateTime );
                    if ( RRet != RET_SUCCESS )
                    {
                        return false;
                    }

                    std::stringstream sstream;
                    sstream << static_cast<int>( rDateTime.date.day ) << "/" << static_cast<int>( rDateTime.date.month ) << "/" << static_cast<int>( rDateTime.date.year) << " " << static_cast<int>( rDateTime.time.hour )
                        << ":" << static_cast<int>( rDateTime.time.minute ) << ":" << static_cast<int>( rDateTime.time.second ) << "." << static_cast<int>( rDateTime.time.millisecond ); 
                    _vsContents.push_back(sstream.str());
                }
                break;
            case R_DOUBLE:
                // Decode DOUBLE
                RDouble rDouble;
                RRet = rDecodeDouble( &m_rDecodeIter, &rDouble );
                _vsContents.push_back(boost::lexical_cast<std::string>(rDouble));
                //m_sStringStream << rDouble << ",";
                break;
            case R_UINT:
                // Decode UINT
                RUInt rUInt;
                RRet = rDecodeUInt( &m_rDecodeIter, &rUInt );
                _vsContents.push_back(boost::lexical_cast<std::string>(rUInt));
                //m_sStringStream << rUInt << ",";
                break;
            case R_ASCII_STRING:
                {
                // Decode STRING
                RBuffer rStringBuffer;
                RRet = rDecodeBuffer( &m_rDecodeIter, &rStringBuffer );
                std::string strData(rStringBuffer.data);
                _vsContents.push_back(strData);
                //m_sStringStream << rStringBuffer.data << ",";
                }
                break;
            case R_NO_DATA:
                RRet = RET_SUCCESS;
                break;
            default:
                RRet = RET_FAILURE;
                break;
            }
        }

        std::stringstream ssReport;
        std::copy(_vsContents.cbegin(),_vsContents.cend(),std::ostream_iterator<std::string>(ssReport,","));
        vsContents.push_back(ssReport.str());

    }
    else
    {
        return false;
    }
    return true;
}

Unfortunately, it has to be in this sequential order as the vector of strings stored will contain a list of comma-separated elements which I will output later to a CSV list. This code simply decodes certain elements and pushes the resulting strings back to a vector of strings which is then put into a std::stringstream.

Does anyone have any suggestions on how to speed up performance?

Solution

First impression:

The parameter list is far far too long, are they really changed every time or does the enclosing object not already hold the values.

Two of the string parameters are not copy but value transferred which is fine if it is needed, else use ref, the places where they are used could have the same problem.

You write that

the vector of strings stored will contain a list of comma-separated elements which I will output later to a CSV list.

If there is no dependence of the comma-separated elements you “just” have to make your own reorder buffer to get them emitted in the right order, then each element can be parallel processed.

pseudo code:

split string in X parts (rDecodeElementEntry?)
make array of return values (_csVector with full length?)
make a queue of tasks of the parts (structs with the needed data)
let some worker threads run through separate parts storing the results in the array.
check for all done
emit the array. (the 3 lines after the while)

Leave a Reply

Your email address will not be published. Required fields are marked *