Ayende @ Rahien

Hi!
My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

, @ Q c

Posts: 18 | Comments: 82

filter by tags archive

Small optimizations? Did you check that idiot checkbox yet?

time to read 2 min | 296 words

I started to write the following code:

operationsInTransactions.GetOrAdd(txId,  new List<Command>())
    .Add(new Command
    {
        Key = key,
        Position = position,
        Type = CommandType.Put
    });

But then I realized that in the happy path, I would always allocate a list, even if I don’t need it, and I changed it to this:

operationsInTransactions.GetOrAdd(txId, guid => new List<Command>())
    .Add(new Command
    {
        Key = key,
        Position = position,
        Type = CommandType.Put
    });

Why am I being stupid?

Hint: It has nothing to do with the stupidity associated with trying to do micro optimizations…


Comments

Torkel

Instead of newing a List you new up a delegate each call to GetOrAdd ?

Ayende Rahien

Well, that was fast.

Yep, that is it.

tobi

No! I think the C# compiler caches delegates that do not close over variables. I have seen that in reflector a while ago. The delegate gets written to a static field.

Dennis

Even so, the speed at which this allocation happens makes it just an insane micro optimization... Unless you are doing it billions of times.

configurator

Tobi is right. Non-closing delegates are converted to static methods. I don't know what happens to ones that use fields, but I'm pretty sure they're cached as well. Only when closing over locals you're creating a mess.

Matt Warren

@configurator I think that if it uses fields it gets converted into a instance method, but I'm not entirely sure.

Daniel

If a delegate closes over local variables, a helper class gets created, so a lambda translates into 2 allocations: the helper class and the delegate.

If a delegate closes only over 'this', it gets compiled into an instance method. These aren't cached, so the lambda causes 1 allocation: the delegate.

If a delegate doesn't close over any variables, then it gets compiled into a static method, and the delegate gets cached using a static field. Once the cache is filled, the lambda doesn't cause any heap allocations.

Comment preview

Comments have been closed on this topic.

FUTURE POSTS

  1. The insidious cost of allocations - 3 hours from now
  2. Buffer allocation strategies: A possible solution - 3 days from now
  3. Buffer allocation strategies: Explaining the solution - 4 days from now
  4. Buffer allocation strategies: Bad usage patterns - 5 days from now
  5. The useless text book algorithms - 6 days from now

And 1 more posts are pending...

There are posts all the way to Sep 11, 2015

RECENT SERIES

  1. Find the bug (5):
    20 Apr 2011 - Why do I get a Null Reference Exception?
  2. Production postmortem (10):
    03 Sep 2015 - The industry at large
  3. What is new in RavenDB 3.5 (7):
    12 Aug 2015 - Monitoring support
  4. Career planning (6):
    24 Jul 2015 - The immortal choices aren't
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats