我有一个 WPF 应用程序,它在大型数据集之间进行大量匹配,目前它使用 C# 和 LINQ 来匹配 POCO 并在网格中显示。随着包含的数据集数量和数据量的增加,我被要求查看性能问题。我今晚测试的假设之一是,如果我们将一些代码转换为 C++ CLI,是否会有实质性差异。为此,我编写了一个简单的测试来创建一个 List<>有 5,000,000 个项目,然后做一些简单的匹配。基本的对象结构是:
public class CsClassWithProps
{
public CsClassWithProps()
{
CreateDate = DateTime.Now;
}
public long Id { get; set; }
public string Name { get; set; }
public DateTime CreateDate { get; set; }
}
我注意到的一件事是,平均而言,对于创建列表然后构建具有偶数 ID 的所有对象的子列表的简单测试,C++/CLI 代码在我的开发机器上慢了大约 8% (64 位 Win8、8GB 内存)。例如,创建和过滤 C# 对象的情况需要大约 7 秒,而 C++/CLI 代码平均需要大约 8 秒。好奇为什么会这样,我使用 ILDASM 来查看幕后发生的事情,并且惊讶地发现 C++/CLI 代码在构造函数中有额外的步骤。先上测试代码:
static void CreateCppObjectWithMembers()
{
List<CppClassWithMembers> results = new List<CppClassWithMembers>();
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < Iterations; i++)
{
results.Add(new CppClassWithMembers() { Id = i, Name = string.Format("Name {0}", i) });
}
var halfResults = results.Where(x => x.Id % 2 == 0).ToList();
sw.Stop();
Console.WriteLine("Took {0} total seconds to execute", sw.Elapsed.TotalSeconds);
}
C#类在上面。 C++ 类定义为:
public ref class CppClassWithMembers
{
public:
long long Id;
System::DateTime CreateDateTime;
System::String^ Name;
CppClassWithMembers()
{
this->CreateDateTime = System::DateTime::Now;
}
};
当我为两个类的构造函数提取 IL 时,这就是我得到的。首先是 C#:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 21 (0x15)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now()
IL_000e: stfld valuetype [mscorlib]System.DateTime CsLibWithMembers.CsClassWithMembers::CreateDate
IL_0013: nop
IL_0014: ret
} // end of method CsClassWithMembers::.ctor
然后是 C++:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 25 (0x19)
.maxstack 2
.locals ([0] valuetype [mscorlib]System.DateTime V_0)
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now()
IL_000b: stloc.0
IL_000c: ldarg.0
IL_000d: ldloc.0
IL_000e: box [mscorlib]System.DateTime
IL_0013: stfld class [mscorlib]System.ValueType modopt([mscorlib]System.DateTime) modopt([mscorlib]System.Runtime.CompilerServices.IsBoxed) CppLibWithMembers.CppClassWithMembers::CreateDateTime
IL_0018: ret
} // end of method CppClassWithMembers::.ctor
我的问题是:为什么 C++ 代码使用本地来存储来自 DateTime.Now 的调用值? ?发生这种情况是否有特定于 C++ 的原因,或者仅仅是他们选择实现编译器的方式?
我已经知道有许多其他方法可以提高性能,而且我知道我已经深入了解了,但我很想知道是否有人可以阐明这一点。好久没搞C++了,随着Windows 8的出现,微软又重新关注C++,我觉得刷新一下就好了,这也是我做这个练习的部分动机,但是两个编译器输出之间的差异引起了我的注意。
最佳答案
System::DateTime CreateDateTime;
这听起来像是一个棘手的问题。您发布的 IL 肯定不会由您发布的代码段生成。您对 CreateDateTime 成员的实际声明是:
System::DateTime^ CreateDateTime;
在您发布的 IL 中清晰可见。它产生了将值类型值转换为引用对象的装箱转换。这是 C++/CLI 中一个非常的常见错误,很容易不小心输入错误。编译器确实应该为其生成警告但没有生成的警告。是的,它使代码陷入困境,装箱转换不是免费的。
否则,您尝试使用 C++/CLI 来加速代码的尝试注定要失败。只要您使用 C++/CLI 编写托管代码,您就会获得与 C# 编译器生成的相同类型的 IL。 C++/CLI 的值(value)在于它能够非常轻松且廉价地调用非托管代码。然而,使用这样的代码不太可能产生好的结果。您调用的非托管代码必须是“实质性的”,这样您从托管代码执行切换到非托管代码执行所产生的损失可以忽略不计。对于不需要任何数据转换的简单转换,该成本徘徊在少数 CPU 周期之间。当您需要执行诸如引脚数组或转换字符串之类的操作时,需要数百个周期。
关于c# - C# 编译器和 C++/CLI 编译器的输出之间的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14027580/
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
我不知道为什么,但是当我设置这个设置时它无法编译设置:static_cache_control,[:public,:max_age=>300]这是我得到的syntaxerror,unexpectedtASSOC,expecting']'(SyntaxError)set:static_cache_control,[:public,:max_age=>300]^我只想将“过期”header设置为css、javaascript和图像文件。谢谢。 最佳答案 我猜您使用的是Ruby1.8.7。Sinatra文档中显示的语法似乎是在Ruby1.
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.