header image
 

Be wary of false LINQ “optimizations”

LINQ in C# is great. It often simplifies things. But at what cost?

Suppose we have a simple task: to iterate over a collection and do something on elements matching a specific predicate/condition:

foreach (var obj in list)
{
    if (!SomeCondition(obj))
        continue;
    DoSomething(obj);
}

It’s tempting to write the above loop in “simplified” form:

foreach (var obj in list.Where(x => SomeCondition(x))
{
    DoSomething(obj);
}

Resharper even suggests such changes by default. It must be good then, right? Not necessary. As always when things involve performance, measurement is the king.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace CsTest
{
    // reference type to simplify field assignment in foreach
    class Num
    {
        public int x;
    }

    class Program
    {
        const int count = 100000;
        const int loops = 10000;

        static void Fun1(List<Num> list)
        {
            for (int loop = 0; loop < loops; loop++)
            {
                foreach (Num num in list)
                {
                    if (num.x < count / 2)
                        continue;
                    num.x = 1;
                }
            }
        }

        static void Fun2(List<Num> list)
        {
            for (int loop = 0; loop < loops; loop++)
            {
                foreach (Num num in list.Where(num => num.x >= count/2))
                {
                    num.x = 1;
                }
            }
        }

        static void Main(string[] args)
        {
            Random rnd = new Random();
            Stopwatch sw = new Stopwatch();
            List<Num> list1 = new List<Num>(count);

            for (int i=0; i<count; i++)
                list1.Add(new Num {x = rnd.Next(count)});
            List<Num> list2 = new List<Num>(list1);

            sw.Restart();
            Fun1(list1);
            sw.Stop();
            Console.WriteLine("Without LINQ: {0}", sw.Elapsed);

            sw.Restart();
            Fun2(list2);
            sw.Stop();
            Console.WriteLine("With LINQ: {0}", sw.Elapsed);
        }
    }
}

On my machine (x86, release) the results are:

Without LINQ: 00:00:06.4973107
With LINQ: 00:00:12.0859563

No matter how big or small loop counters are, LINQ version is consistently 2x slower than non-LINQ one. Surprise, eh?

It’s not that much of a surprise if you think about it. Where() operator essentially creates a temporary collection with elements that satisfy the predicate. So you not only pay the price of increased CPU load, but also increased number of allocated objects and increased GC pressure. Not a good thing, especially if that code runs once per frame or in other tight spots.

As always, take nothing for granted – observe and measure!

Optimizing Garbage Collector performance in your .NET application

Garbage collection (GC) statistics is one of the main performance metrics for any .NET application. I won’t go into details on how it works, you can read about that here for example. Below are some very basic facts:

  • Managed heap is organized into generations: Gen0, Gen1 and Gen2. Every object existing on the heap belongs to one.
  • Garbage collector works on each generation separately. If an object survives GC collection (because it’s still referenced) it is moved to the older generation: from Gen0 to Gen1 and from Gen1 to Gen2. This is called “object aging”.
  • Gen0 and Gen1 collections are relatively fast compared to Gen2, which is much slower.

This already gives us the idea on how to optimize GC performance: Don’t keep references to objects for too long if you don’t have to. This way not many objects will survive collection and get promoted to a slower generation.

Alright, but how to actually check those GC statistics? There are a few ways. For a quick assessment you can use Process Explorer. Just double-click on your process (managed processes have yellow background) and click on the “.NET Performance” tab, then select “.NET CLR Memory” option. It’s really handy.

Continue reading ‘Optimizing Garbage Collector performance in your .NET application’

Hibernation woes part 2

I’ve written about my laptop problems before. I’ve got it to “somewhat work” by setting all power options to sleep, as it just seemed to work like hibernation. Hybrid sleep is a power option that’s supposed to behave like that, but I have it disabled.

Anyway, the machine still sometimes woke up overnight and drained its battery without suspending itself. It was not happening every time. Tonight it happened again and I was sufficiently annoyed to investigate the matter a bit more. First step: the event viewer:

Log Name:      System
Source:        Microsoft-Windows-Kernel-Power
Date:          2011-08-14 02:41:58
Event ID:      42
Task Category: (64)
Level:         Information
Keywords:      (4)
User:          N/A
Computer:      omeg-mobile2
Description:
The system is entering sleep.

Sleep Reason: Button or Lid

That’s the initial sleep when I was going to bed.

Log Name:      System
Source:        Microsoft-Windows-Power-Troubleshooter
Date:          2011-08-14 03:12:16
Event ID:      1
Task Category: None
Level:         Information
Keywords:      
User:          LOCAL SERVICE
Computer:      omeg-mobile2
Description:
The system has resumed from sleep.

Sleep Time: ‎2011‎-‎08‎-‎14T01:12:09.550008400Z
Wake Time: ‎2011‎-‎08‎-‎14T01:12:06.450004100Z

Wake Source: S4 Doze to Hibernate

And here we have the wake event. Notice that it happened exactly 30 minutes after entering sleep. “S4 Doze to Hibernate” seems to be an attempt to enter hibernation state. Too bad hibernation doesn’t work for some reason (it’s enabled, swap file is large enough, enough disk space etc). So hibernate failed and the machine just stayed awake. Still, it should enter sleep again after some time…

After checking my advanced power options, I found the culprit. Value 30 was set under “Sleep – Hibernate after – On battery”. I’ve set it to 0 “never”, same like the “Plugged in” option. I hope it will work.

There is still the issue of sleep behaving like hybrid sleep only when the Hybrid sleep setting is turned off. I’ve tried turning that option (Sleep – Allow hybrid sleep) on – it resulted in sleep behaving like, well, normal sleep (power LED not blinking, machine waking up on mouse/keyboard input). It’s like the options were reversed somehow. What’s even more curious, powercfg -a lists hybrid sleep (S3) as the only power state available:

The following sleep states are available on this system: Standby ( S3 ) Hibernate Hybrid Sleep
The following sleep states are not available on this system:
Standby (S1)
        The system firmware does not support this standby state.
Standby (S2)
        The system firmware does not support this standby state.

Go figure.

More progress

GWEN.NET

GWEN.NET on Google Code

https://code.google.com/p/gwen-dotnet/
Already reported the first bug… 😉

Little teaser…

GWEN conversion status

C# port of GWEN is going pretty well so far. I’ve got most of the framework classes translated and the project even compiles now. Time to port one of the renderers and see what will fail…

This project also reminded my why I prefer C# over C++ nowadays. It simplifies so many things and memory management is just one of them. Events/messages, basic things like strings/unicode. No header hell. And of course no f**king STL (yes, I loathe the thing). I’ll end with a simple snippet…

void Gwen::Anim::Cancel( Gwen::Controls::Base* control )
{
        Gwen::Anim::Animation::List::iterator iAnimations;
        if ((iAnimations = g_Animations.find(control)) != g_Animations.end())
        {
                Gwen::Anim::Animation::ChildList &ChildAnimationsForControl = iAnimations->second;
                Gwen::Anim::Animation::ChildList::iterator iAnimationChild = ChildAnimationsForControl.begin();
                if (iAnimationChild != ChildAnimationsForControl.end())
                {
                        do
                        {
                                delete (*iAnimationChild);
                        }while(++iAnimationChild != ChildAnimationsForControl.end());
                }
                g_Animations.erase(iAnimations);
        }
}

vs

public static void Cancel(Base control)
{
    if (g_Animations.ContainsKey(control))
    {
        g_Animations[control].Clear();
        g_Animations.Remove(control);
    }
}

The quest for C# OpenGL GUI

I need a GUI framework for C# that is renderable in an OpenGL context. It needs to be skinnable and have at least the standard GUI controls implemented. It seems easy, but after extensive searching for a week or two, I found nothing. I’m using SFML graphics library. Some candidates:

  • sfgui: looks promising, but no C# bindings out of the box. Unfinished.
  • cpGUI: too limited, C++ only.
  • CEGUI: C++, seems overly complicated. C# port seems dead.
  • GWEN: stumbled upon it by accident while browsing SFML forums. C++, small but have lots of features, skinnable. Written by Garry Newman. 😉

There might’ve been others, but you can see the trend – no usable C# ports. C++ is tricky when it comes to interop with C#, normal P/Invoke is not able to bind to C++ classes from DLL. I didn’t try to achieve such integration before, but GWEN looks too good not to try (and C++ examples work at least). So I googled about C++/C# interop and basically found two options:

  • Creating C++/CLI managed proxy that will act as a bridge between C# and C++ (MSDN explanation). I’ve never touched C++/CLI and would prefer to not need to.
  • Using SWIG. SWIG is supposed to be able to parse C++ code semantically and create wrappers for various languages. It sounds almost too good to be true… and it is. Documentation for it is massive. It has problems with custom operators and same-named identifiers in different namespaces. After spending most of today trying to get it work, I gave up.

So, what we have left? Nothing? No! We can always rewrite the whole thing in C#! Crazy, you say? Not so much I think. GWEN is really not a big project and it’s written in very clean C++ from what I can tell. Rendering portion is neatly abstracted, it even has a separate SFML renderer. I’d rather not “waste time” on GUI library, but if I manage to do that it will be great for the community. We’ll see…

Edit: get it here: GWEN.Net

I hate fucking mosquitos!

My hatred for those little f**kers burns with the power of a thousand suns. That is all.

Windows 7/Vista – Network Location Monitor

The story

This utility started as a result of experiencing weird and annoying glitch in Windows 7/Vista. Every time my home PC lost internet connection for some reason (even momentarily), its network location changed from “Private” to “Public”. Seemed like Windows didn’t recognize the connection, since its name also changed to “Unidentified network”.

I often use Remote Desktop to connect to the home PC, so this was very annoying: Public network location makes remote connections impossible. After extensive googling I’ve found no solution that was working for me. Maybe it’s Windows, maybe my router, maybe the ISP, I don’t know. But I needed to do something about it.

I could try to debug the issue but I’m rather lazy when it comes to such things. So I wrote a simple service that monitors changes to network connections. If any of configured connections’ location changes from Private, the service sets it to Private again. Simple, easy and most important – it works.

Usage

Network Location Monitor is written in C# 4.0 and requires .NET Framework 4 to run. If you don’t have it, get it here:
http://www.microsoft.com/download/en/details.aspx?id=17851

First, run install.bat as an administrator. It installs the service (NetLocationMonitor). Then, run start.bat (also as admin) to start the service. That’s it, service is set to autostart, so it starts with Windows. stop.bat stops the service and uninstall.bat, well, uninstalls it.

WARNING: only start the service if your machine is connected to a trusted network! NetLocationMonitor will set any new connections to Private!

Technical details

Service name is NetLocationMonitor. It runs as LocalSystem – unfortunately it’s needed for the access rights to change network type. It writes an entry to Application event log whenever new network is being detected and corrected.

NetTest project in the sources is an artifact of an earlier version, when NLM only monitored specific networks for changes. That didn’t really work, since when the glitch happens, a new network is being added – the old one doesn’t change.

License

Network Location Monitor is placed in the public domain.

Download

Network Location Monitor