News

My Stats

  • Posts - 21
  • Comments - 20
  • Trackbacks - 0

Twitter












Recent Comments


Recent Posts


Archives


Post Categories


 

A few years back I bumped into a rather peculiar optimization case. I did some performance analysis on mesh loading because at the time it took about 15 seconds to load a relatively small ANSI encoded mesh file. 15 seconds! I tracked the reason down to a call to atof, which is what I would use for parsing floating point values from strings.

Having found out what the reason was I decided to write my own implementation of floating point parsing that would concentrate on the essentials like speed instead of doing all kinds of culture checks and what not. Having done this I found out it was a very good idea indeed. Loading times dropped from 15 seconds to much under a second! If my memory doesn’t deceive me the speedup factor was somewhere around 100.

I recently tested whether the issue with atof was still there and it turns out it’s not that bad but it’s there all right. Testing with 1 000 000 iterations it took about 1.318 seconds from atof and 0.1016 seconds from my custom implementation.

Here’s the implementation of the function. It could still be optimized further, of course, and the precision is not as good as with atof, but it’s good enough.

RRFloat_t ParseFloat( const RRChar_t *str )
{
    RRUInt_t offset = 0;

    while ( str[offset] != '\0' &&
            str[offset] != '-' &&
            ( str[offset] < '0' ||
                str[offset] > '9' ) ) {
        offset++;
        if ( str[offset] == '\0' ) {
            return 0.0f;
        }
    }

    RRFloat_t val = 0.0f;
    RRBool_t neg = false;
    if ( str[offset] == '-' )
    {
        offset++;
        neg = true;
    }
    RRFloat_t curNom = 1.0f;
    while( str[offset] != '.' )
    {
        val = val + (RRFloat_t)( str[offset] - '0' );
        offset++;

        switch( str[offset] )
        {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
        case '.':
            break;
        default:
            if ( neg )
                return -val;
            return val;
        }

        if ( str[offset] != '.' )
            val *= 10.0f;
    }
    offset++;
    curNom = 0.1f;
    while( str[offset] >= '0' && str[offset] <= '9' )
    {
        val = val + curNom * (RRFloat_t)( str[offset] - '0' );
        curNom *= 0.1f;
        offset++;
    }

    if ( neg )
        return -val;
    return val;
}

Simple enough. What’s the purpose of this blog post, you might think? When need be, don’t be afraid to get your hands dirty and just do it yourself!


 

Microsoft isn’t the only one who seems to be pushing native computing once again. We’re now seeing Google at the same table with the current beta release of Chrome. Yes, Chrome now supports native applications to be embedded in a web site and it’s just like embedding JavaScript. More information can be found in here: http://chrome.blogspot.com/2011/08/building-better-web-apps-with-new.html.

The native client SDK runs a sandbox environment which means Chrome handles security of the module just like it would with JavaScript while providing the module access to 2D/3D graphics rendering, input,  multithreading, etc. without risking any principles of tranditional C++. The system should also comply with standards because the compiler is based on the default GCC compiler.

Life is good! Iloiset kasvot


 

Just recently I bumped into a bug that looked a bit odd at first. I was wondering why our line rendering was outputting only a single line for some wireframe meshes. This happened only on an AMD Radeon graphics card. After some digging into this I found out that the reason was that NVIDIA and AMD drivers map buffer memory in a slightly different manner. AMD seems to reuse system memory regions for buffer mapping while NVIDIA seems to prefer allocating new regions for this purpose.

I realized this as I had mapped an index buffer into which I read the mesh index data and had then accidentally unmapped it. After this I had mapped another buffer that would contain the line indices that were generated from the previously mapped index buffer. The driver, however, mapped the second buffer into the same memory region resulting in me modifying the source information while I was generating the line information. Because the first indices in the triangle buffer were 1, 0 this meant that I would generate lines 1, 0, 0, 0 and so on.

The lesson of all this? Be careful with your buffer mappings and you might even want to null out your pointers after unmapping to at least catch a null pointer exception.


 

Just recently Diego and Charles starred in the first issue of the monthly show GoingNative that concentrates on native C++ development: http://channel9.msdn.com/Shows/C9-GoingNative/GoingNative-0-Help-us-fly-this-plane-Some-modern-C-Meet-Ale-Contenti.

The first issue is a great introduction to the native world but it also promises to cater to us native C++ speakers. It’s a blast to already see 60,436 views of the show!

Go native, go!