如何在基准测试时使缓存失效?

发布于 2024-08-29 19:24:01 字数 3561 浏览 3 评论 0原文

我有这段代码,当交换UsingAs和UsingCast的顺序时,它们的性能也会交换。

using System;
using System.Diagnostics;
using System.Linq;

using System.IO;

class Test
{
    const int Size = 30000000;

    static void Main()
    {
        object[] values = new MemoryStream[Size];



        UsingAs(values);
        UsingCast(values);


        Console.ReadLine();
    }

    static void UsingCast(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {
            if (o is MemoryStream)
            {
                var m = (MemoryStream)o;
                sum += (int)m.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("Cast: {0} : {1}", sum,
                          (long)sw.ElapsedMilliseconds);
    }

    static void UsingAs(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {

            if (o is MemoryStream)
            {
                var m = o as MemoryStream;
                sum += (int)m.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("As: {0} : {1}", sum,
                          (long)sw.ElapsedMilliseconds);
    }


}

输出:

As: 0 : 322
Cast: 0 : 281

执行此操作时...

UsingCast(values);
UsingAs(values);

...执行此操作时的结果:

Cast: 0 : 322
As: 0 : 281

执行此操作时...

UsingAs(values);

...执行此操作的结果:

As: 0 : 322

执行此操作时:

UsingCast(values);

...执行此操作的结果:

Cast: 0 : 322

除了独立运行它们之外,如何<使缓存无效,以便进行基准测试的第二个代码不会接收第一个代码的缓存内存?

撇开基准测试不谈,只是喜欢现代处理器执行这种缓存魔法的事实:-)

[编辑]

建议尝试这个更快的代码(据说)

static void UsingAsAndNullTest(object[] values)
{        
    Stopwatch sw = Stopwatch.StartNew();
    int sum = 0;
    foreach (object o in values)
    {
        var m = o as MemoryStream;
        if (m != null)
        {                
            sum += (int)m.Length;
        }
    }
    sw.Stop();
    Console.WriteLine("As and null test: {0} : {1}", sum,
                      (long)sw.ElapsedMilliseconds);
}

......结果是这样的:

As and null test: 0 : 342

慢于上面的两个代码

[编辑]:

建议将每个例程交给他们自己的副本...

static void UsingAs(object[] values)
{
    object[] a = values.ToArray();

    Stopwatch sw = Stopwatch.StartNew();
    int sum = 0;
    foreach (object o in a)
    {

        if (o is MemoryStream)
        {
            var m = o as MemoryStream;
            sum += (int)m.Length;
        }
    }
    sw.Stop();
    Console.WriteLine("As: {0} : {1}", sum,
                      (long)sw.ElapsedMilliseconds);
}

static void UsingCast(object[] values)
{
    object[] a = values.ToArray();

    Stopwatch sw = Stopwatch.StartNew();
    int sum = 0;
    foreach (object o in a)
    {
        if (o is MemoryStream)
        {
            var m = (MemoryStream)o;
            sum += (int)m.Length;
        }
    }
    sw.Stop();
    Console.WriteLine("Cast: {0} : {1}", sum,
                      (long)sw.ElapsedMilliseconds);
}

...输出:

Cast: 0 : 282
As: 0 : 282

现在他们有相同的结果,谢谢Remus!

独立运行 Cast 和 As,它们也会产生相同的结果(即 282)。现在,至于为什么当它们获得自己的数组副本时它们会变得更快(从 322 毫秒降低到 282 毫秒),我无法从中得出任何结论:-) 这完全是另一个故事

I have this code, that when swapping the order of UsingAs and UsingCast, their performance also swaps.

using System;
using System.Diagnostics;
using System.Linq;

using System.IO;

class Test
{
    const int Size = 30000000;

    static void Main()
    {
        object[] values = new MemoryStream[Size];



        UsingAs(values);
        UsingCast(values);


        Console.ReadLine();
    }

    static void UsingCast(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {
            if (o is MemoryStream)
            {
                var m = (MemoryStream)o;
                sum += (int)m.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("Cast: {0} : {1}", sum,
                          (long)sw.ElapsedMilliseconds);
    }

    static void UsingAs(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {

            if (o is MemoryStream)
            {
                var m = o as MemoryStream;
                sum += (int)m.Length;
            }
        }
        sw.Stop();
        Console.WriteLine("As: {0} : {1}", sum,
                          (long)sw.ElapsedMilliseconds);
    }


}

Outputs:

As: 0 : 322
Cast: 0 : 281

When doing this...

UsingCast(values);
UsingAs(values);

...Results to this:

Cast: 0 : 322
As: 0 : 281

When doing just this...

UsingAs(values);

...Results to this:

As: 0 : 322

When doing just this:

UsingCast(values);

...Results to this:

Cast: 0 : 322

Aside from running them independently, how to invalidate the cache so the second code being benchmarked won't receive the cached memory of first code?

Benchmarking aside, just loved the fact that modern processors do this caching magic :-)

[EDIT]

As advised to try this faster code(supposedly)...

static void UsingAsAndNullTest(object[] values)
{        
    Stopwatch sw = Stopwatch.StartNew();
    int sum = 0;
    foreach (object o in values)
    {
        var m = o as MemoryStream;
        if (m != null)
        {                
            sum += (int)m.Length;
        }
    }
    sw.Stop();
    Console.WriteLine("As and null test: {0} : {1}", sum,
                      (long)sw.ElapsedMilliseconds);
}

...The result is this:

As and null test: 0 : 342

Slower than the two codes above

[EDIT]:

As advised to hand each routine their own copy...

static void UsingAs(object[] values)
{
    object[] a = values.ToArray();

    Stopwatch sw = Stopwatch.StartNew();
    int sum = 0;
    foreach (object o in a)
    {

        if (o is MemoryStream)
        {
            var m = o as MemoryStream;
            sum += (int)m.Length;
        }
    }
    sw.Stop();
    Console.WriteLine("As: {0} : {1}", sum,
                      (long)sw.ElapsedMilliseconds);
}

static void UsingCast(object[] values)
{
    object[] a = values.ToArray();

    Stopwatch sw = Stopwatch.StartNew();
    int sum = 0;
    foreach (object o in a)
    {
        if (o is MemoryStream)
        {
            var m = (MemoryStream)o;
            sum += (int)m.Length;
        }
    }
    sw.Stop();
    Console.WriteLine("Cast: {0} : {1}", sum,
                      (long)sw.ElapsedMilliseconds);
}

...Outputs:

Cast: 0 : 282
As: 0 : 282

Now they have the same results, thanks Remus!

Running Cast and As independently, they also yield the same result(i.e. 282). Now, as for why they become faster (from 322 down to 282 milliseconds) when they are handed their own copy of array, I can't make anything out of it :-) That's entirely another story

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

长安忆 2024-09-05 19:24:01

如果您想从 L2 缓存和 TLB 未命中的情况中删除,则只需对相同大小的不同 MemoryStream 调用第二个测试即可。

If you want to take out of the picture the L2 cache and the TLB misses then simply call the second test on a different MemoryStream of the same size.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文