【发布时间】:2010-04-21 03:03:25
【问题描述】:
我有这段代码,当交换 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 毫秒),我无法从中得到任何东西 :-) 这完全是另一回事
【问题讨论】:
-
您知道最快的方法是不检查
is,使用as运算符并测试==null的结果。 -
我不是在问如何让代码更快。我在问如何进行适当的基准测试。而且我有一种暗示,有人会建议使用
as并测试==null(有人有),遗憾的是,这种方法比上面的两个代码都慢
标签: c caching benchmarking cache-invalidation