我正在帮助的项目中有一个人在性能重要代码中随处放置unsafe
标记,无论是否需要。通常这个标签可以安全地移除,但不幸的是,很难证明他,他不应该这样做。任何人都可以给我一篇好的权威文章,这证明了我或他的观点,所以我们终于可以解决这个问题吗?
他使用unsafe的代码示例:
unsafe
{
writeableBmp.CopyPixels(new Int32Rect(1, 0, (int)(width - 1), (int)height - 1), buffer, writeableBmp.BackBufferStride, 0);
writeableBmp.Lock();
writeableBmp.WritePixels(new Int32Rect(0, 0, (int)width - 1, (int)height - 1), buffer, writeableBmp.BackBufferStride, 0, 0);
writeableBmp.AddDirtyRect(new Int32Rect(0, 0, (int)width - 1, (int)height - 1));
writeableBmp.Unlock();
}
他的观点是他读到了需要unsafe
的地方,并通过给编译器提示提高了性能,代码片应该以不同方式编译。
答案 0 :(得分:3)
根据http://msdn.microsoft.com/en-us/library/t2yzs44b.aspx,不安全只会创建一个不安全的上下文。只有在使用被认为不安全的指针算法等时才需要这样做,因此需要创建不安全的上下文。
在任何其他情况下,它都没有任何好处,因为它不会禁用任何东西。
使用和不使用它来配置代码或检查MSIL以证明它。
只需删除它,如果有不安全的代码,编译器会告诉你。
一些方法:
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
namespace CSharpTestbench
{
class Program
{
static void Main(string[] args)
{
int x = 42;
if (x == 42)
{
Console.WriteLine("it is 42");
}
}
}
}
以这种方式查找非优化的MSIL代码:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 30 (0x1e)
.maxstack 2
.locals init ([0] int32 x,
[1] bool CS$4$0000)
IL_0000: nop
IL_0001: ldc.i4.s 42
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: ldc.i4.s 42
IL_0007: ceq
IL_0009: ldc.i4.0
IL_000a: ceq
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: brtrue.s IL_001d
IL_0010: nop
IL_0011: ldstr "it is 42"
IL_0016: call void [mscorlib]System.Console::WriteLine(string)
IL_001b: nop
IL_001c: nop
IL_001d: ret
} // end of method Program::Main
用不安全的结果装饰它:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 32 (0x20)
.maxstack 2
.locals init ([0] int32 x,
[1] bool CS$4$0000)
IL_0000: nop
IL_0001: nop
IL_0002: ldc.i4.s 42
IL_0004: stloc.0
IL_0005: ldloc.0
IL_0006: ldc.i4.s 42
IL_0008: ceq
IL_000a: ldc.i4.0
IL_000b: ceq
IL_000d: stloc.1
IL_000e: ldloc.1
IL_000f: brtrue.s IL_001e
IL_0011: nop
IL_0012: ldstr "it is 42"
IL_0017: call void [mscorlib]System.Console::WriteLine(string)
IL_001c: nop
IL_001d: nop
IL_001e: nop
IL_001f: ret
} // end of method Program::Main
当然,两者都编译为/不安全。
实际上,不安全的代码有更多的指令,它们会产生稍微大一点的可执行文件,但应该可以忽略不计。不安全的调用只是被NOP
CIL
指令取代,这些指令实际上“什么都不做”,期望增加可执行文件的大小(http://en.wikipedia.org/wiki/List_of_CIL_instructions)。
它增加了缩进并使代码更难阅读,因为它还意味着存在不安全的代码。
R#也说没必要。
开发人员有什么证据支持这种说法?
答案 1 :(得分:3)
以下是您的链接:http://en.wikipedia.org/wiki/Premature_optimization#When_to_optimize
除了他在假设不安全方面完全错误使代码更快的原因之外,使用随机关键字可能影响性能并不是任何专业人员开发代码的方式。
首先,编写代码,在性能和代码复杂性之间取得良好的平衡 - 即,如果您可以编写运行速度更快的更干净的编码器,那就去做吧。如果你能编写运行得更快的更脏的代码,那就不要了。 其次,弄清楚性能是否足够。如果是的话,你就完成了。如果不是,请确定哪个部分最能影响您的表现,修复那部分,然后单独留下其他部分。
回到不安全状态:不安全并不快。如果您知道如何执行此操作,它允许您编写速度更快,安全性更低(a.k.a.不安全)的代码,允许您编译否则将无法编译的代码。但是,对普通代码进行不安全处理并不会产生任何积极的性能差异。
不幸的是,对你来说,你的同事是如此遥远,以至于很难找到专门针对这个问题的文章“默认情况下,安全代码更快”。因为默认情况下不安全的代码更快,任何地方既没有陈述也没有暗示,举证责任应该在他身上。但是,如果没有任何有能力的前辈或经理,可能很难说服他就是这种情况。所以我能看到的最好的攻击点就是过早的优化 - 如果他的代码更复杂,他就必须证明它。