Are you familiar with [ThreadStatic]?


If you’re stuffing anything in thread local storage, you might be interested in the performance comparison between Thread.SetData and [ThreadStatic].


ThreadStatic is super-cool, if you have a static variable, you can make it static “per-thread” by placing the attribute on top.  This is one easy way to get around the thread-safety issues of working with statics – as they are per-thread, you do not have to take a lock when updating them.


[ThreadStatic]
private static string Foo;


Now the thing that can trip you up is initialization. 


[ThreadStatic]
private static string Foo = “the foo string”;


The ThreadStatic is initialized in the static constructor – which only executes once.  So only the very first thread is assigned “the foo string” when the static constructor executes. When accessed in all subsequent threads, Foo is left at the uninitalized null value.


The best way to work around this is to use a property to access the Foo prop.


[ThreadStatic]
private static string _foo;


public static string Foo {
   get {
     if (_foo == null) {
         _foo = “the foo string”;
     }
     return _foo;
   }
}


If you have something that can be legitimately set to null, you can always use a thread-static boolean “_fooInitialized”.


[ThreadStatic]
private static string _foo;


[ThreadStatic]
private static bool _fooInitialized;


public static string Foo {
   get {
     if (!_fooInitialized) {
         _fooInitialized = true;

         _foo = “the foo string”;
     }
     return _foo;
   }
}


And if you have a lot of booleans, you may want to save space; believe it or not a boolean hogs precious bits (for extra credit try printing out Marshal.SizeOf(typeof(bool)). 


You save on space by lumping them all into one bitvector… 


        [ThreadStatic]
        private static string _foo;


        [ThreadStatic]
        private static string _goo;


        [ThreadStatic]
        private static BitVector32 _state = new BitVector32();
 


        private const int stateFooInitialized = 0x0001;
        private const int stateGooInitialized = 0x0002;
        // … 0x0004, 0x0008 …


        public static string Foo {
            get {
                if (!_state[stateFooInitialized]) {
                    _state[stateFooInitialized] = true;
                    _foo = “the foo string”;
                }
                return _foo;
            }
        }


        public static string Goo {
            get {
                if (!_state[stateGooInitialized]) {
                    _state[stateGooInitialized] = true;
                    _goo = “the goo string”;
                }
                return _goo;
            }
        }


Comments (12)

  1. jfo's coding says:

    Phil asks:

    "Your last post mentions using Marshal.SizeOf to get the byte size of a type that can be…

  2. Kobush says:

    Instead of figuring out the correct bitmask for your state consts yourself, you can use the static BitVector32.CreateMask() method to do it for you. In this case you can write:

    static readonly int stateFooInitialized = BitVector32.CreateMask();

    static readonly int stateGooInitialized = BitVector32.CreateMask(stateFooInitialized );

    Note that in second call you should put the previous mask.

    Another great feature of BitVector32 I’ve learned recently is bit packing. You can read more here: http://adoguy.com/viewrant.aspx?id=2016

  3. Ben Hollis says:

    Man, I always learn the coolest things from your blog.

    It’s interesting, I love annotations, but I find them much harder to discover than normal Framework classes. I stumble on new classes and methods all the time via Intellisense, but I don’t know that I’ve ever found an annotation that way.

  4. jfoscoding says:

    Kobush – CreateMask is really cool.  I believe theres also something like CreateSection if you want to map in more than one bit.  Some folks use this to stash away enumerations.

    The reason I didn’t use CreateMask here is that I would have to store it off statically, which meant that instead of holding onto booleans, I was holding on to integers – so basically I wouldn’t shave off any room.

    The const would get replaced by the compiler, so it would not take up room.

    I find CreateMask is only helpful when you’re remembering non-static state.

  5. Kobush says:

    Ok, in that case it makes perfect sense to use const instead. I’ve only used BitVector32 for classes that have lots of instances (e.g. ORM metadata), so sacrificing few statics to store masks wasn’t big deal.

    Thanks for another great .NET tip!!!

  6. ricom says:

    With this code:

    [ThreadStatic]

    private static BitVector32 _state = new BitVector32();

    The reason this works is that BitVector32 is a value type so there is no real pointer initialization and it will be ok if subsequent threads don’t run that constructor.

    If that wasn’t the case then we would just be trading one initialization problem (the strings) for another (the BitVector).

    Also, we’d probalby have race-conditions galore trying to atomically update a bit in the BitVector except that by design this BitVector is thread local.

    Be careful out there, setting a bit is not generally an atomic operation.  I bet this guy doesn’t use InterlockedCompareExchange to set the bit — I’d be surprised if it did because that would tank the perf in the normal cases.

  7. jfoscoding says:

    Rico – the most common place for ThreadStatic to be used is for UI caches.  Quite a lot of the graphic objects cannot be accessed from another thread.  For example, holding onto a System.Drawing.Image or Graphics object statically is a big nono.

  8. A long time ago Patrick Cauldwell wrote up a technique for managing external files within unit tests