如何在基准测试时使缓存失效?
我有这段代码,当交换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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您想从 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.