OpenImageIO/oiio — pull request #846 by lgritz (2014-05-06 00:24:19+00:00)
Title: ustring speedups

ustring was designed assuming that there would be very frequent comparison and assignment, relatively rare construction from C strings, and *extremely* rare (in the course of a long render, say) construction of unique ustrings that had not yet been encountered.

But, in any case, we have a situation where an OSL user wrote a shader that resulted in extremely heavy ustring construction (creating new strings on every shade in a way that couldn't be constant-folded) and when running with many threads concurrently, there was a severe thread bottleneck, with this ustring construction being a major portion of runtime. Ouch!

I was able to speed things up substantially with a few changes, primarily:

1. Switching the underlying hash table in ustring.cpp from unordered_map to unordered_map_concurrent (much like we did for ImageCache some time back to remove thread bottlenecks).

2. Cache alignment of some of the atomics internal to ustring.cpp and unordered_map_concurrent to eliminate "false sharing."

On my benchmark (via OSL, which heavily uses ustring construction in this manner, but is not by any means "only" ustring construction), this is actually a tad slower with a single thread -- 1-2%. But the more threads, the bigger a speedup as the bottleneck is eliminated: 13% overall runtime speedup for 4 threads, 25% for 8 threads. That's overall speedup of the OSL benchmark, not exclusively ustring construction time. I'm sure that the speedup anybody else encounters will vary widely depending on the nature of your application. For a task that doesn't involve very frequent ustring construction from C strings, there will probably be no measurable difference at all.

ustring construction still ain't cheap, but with this patch, at least it doesn't get worse and worse as you add threads.