1
\$\begingroup\$

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?

\$\endgroup\$
  • \$\begingroup\$ Unfortunately, there are so many unknown types and methods that I really cannot guess what is the most slowing part. How do you call it? Any mutexes (no active waiting)? Some profiling? Did you measure which part is eating the most of the CPU time? There is simply nothing I can take, compile and play with to find the performance problem. \$\endgroup\$ – firda Sep 10 '14 at 17:42
1
\$\begingroup\$

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)
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.