Daily Usage Issues

Why is this weakref test failing according to NCrunch but passing according to visual studio?

Started by Strilanc on 6,773 views

NCrunch seems to be preventing the garbage collection of objects that only have weak references.

    [TestMethod]
    public void WeakReferencesCanBeCollected() {
        var r = new object();
        var w = new WeakReference<object>(r);
        r = null;
        GC.Collect();
        Assert.IsFalse(w.TryGetTarget(out r)); // NCrunch says fails here, but MSTest passes it
    }


This also happens when debugging. If I use NCrunch's "Debug covering test" it throws, but if I use visual studio's "Debug test" then it passes.

My best guess is that I'm relying on undefined behavior. The language semantics might not require the garbage collector to clean up everything, despite being asked for a full collection. I'm pretty sure that the debugger prolongs the life of local variables (technically they can be collected after last use, but the debugger keeps them around until the end of their scope [see: GC.KeepAlive]), and maybe something similar is happening.

The reason I want this sort of test is to test for particular runtime optimizations. For example, list.Skip(2).Skip(2) should be optimized into list.Skip(4) and this can be detected from the outside by the collection of the intermediate list. There's a few of these tests in https://github.com/Strilanc/LinqToCollections .

Edited

This behaviour is due to the effect of NCrunch's instrumentation on garbage collection within the CLR. You can find some more details about this at: http://forum.ncrunch.net/yaf_postst182_Liveness-extended-with-enabled-timing.aspx

To work around this problem, you can suppress code coverage for the full method above, or you can switch off performance analysis for the project that contains it.

Post a reply

Log in to reply.