C# 将变量赋给表达式是否更节省内存?
什么更有效率C# 将变量赋给表达式是否更节省内存?,c#,.net,C#,.net,什么更有效率 decimal value1, value2, formula 这: 或者这个: for(int i = 0; i>1000000000000; i++) { value1 = getVal1fromSomeWhere(); value2 = getVal2fromSomeWhere(); formula = value1*value2 + value1/value2; SendResultToA(formul
decimal value1, value2, formula
这:
或者这个:
for(int i = 0; i>1000000000000; i++)
{
value1 = getVal1fromSomeWhere();
value2 = getVal2fromSomeWhere();
formula = value1*value2 + value1/value2;
SendResultToA(formula);
SendResultToA(formula);
}
直觉上我会选择后者
我想在每次迭代(decimal
,formula
)时都有一个额外的赋值,而在没有额外变量的情况下不断地执行计算,这两者之间有一个折衷
编辑:嗯。上帝每次我问问题时都要经过这个过程吗?
如果我问它,那是因为它对我来说很重要,伙计们。 不是每个人都生活在一个温和的非记忆批判的世界里,醒醒吧! 这只是一个过于简单的例子。我正在做数以百万计的科学计算和云计算多线程的工作,不要把我当成傻瓜:-)
所以是的,肯定每纳秒都很重要
<强> ps:强>我几乎后悔C++和指针。自动内存管理和GC肯定会让开发人员变得无知和懒惰:-P
除非你一秒钟要做数万次,否则这一点都不重要。优化可读性和可维护性
编辑:仇恨者会仇恨的,好吧,好了,给你。我的代码:static void MethodA()
{
for (int i = 0; i < 1000; i++) {
var value1 = getVal1fromSomeWhere();
var value2 = getVal2fromSomeWhere();
SendResultToA(value1 * value2 + value1 / value2);
SendResultToB(value1 * value2 + value1 / value2);
}
}
static void MethodB()
{
for (int i = 0; i < 1000; i++) {
var value1 = getVal1fromSomeWhere();
var value2 = getVal2fromSomeWhere();
var formula = value1 * value2 + value1 / value2;
SendResultToA(formula);
SendResultToB(formula);
}
}
static void MethodA()
{
对于(int i=0;i<1000;i++){
var value1=getval1fromwhere();
var value2=GetVal2Fromsomeone();
SendResultToA(value1*value2+value1/value2);
SendResultToB(value1*value2+value1/value2);
}
}
静态void方法b()
{
对于(int i=0;i<1000;i++){
var value1=getval1fromwhere();
var value2=GetVal2Fromsomeone();
var公式=value1*value2+value1/value2;
SendResultToA(配方奶粉);
SendResultToB(公式);
}
}
以及它们生成的实际x86程序集:
方法A:
方法B:
它们非常长,因为它内联了getVal[1/2]fromwhere和SendResultTo[A/B],我将其连接到Random和Console.WriteLine。我们可以看到,事实上,CLR和抖动都不够聪明,无法重复之前的计算,因此我们额外花费了318字节的x86字节代码来做额外的计算
然而,请记住这一点——即使是一个额外的页面错误或磁盘读/写,您通过这些优化获得的任何收益都会立即变得无关紧要。如今,CPU很少成为大多数应用程序的瓶颈——I/O和内存都是。针对空间局部性进行优化(即使用连续阵列以减少页面错误),并减少磁盘i/O和硬页面错误(即加载不需要的代码需要操作系统对其进行故障处理) 从某种程度上说,我认为你是对的。两者都具有同等的可读性(可以说) 请记住,循环迭代次数与本地内存需求无关。您只讨论了几个额外的字节(无论如何,该值将被放在堆栈上,以便传递到函数);然而,通过缓存计算结果而节省的周期*确实会随着迭代次数显著减少
*也就是说,前提是编译器不为您执行此操作。查看每种情况下生成的IL会很有启发性。首先是概要文件,并且只有在必要时才进行这种微观优化。否则会优化可读性。在你的情况下,我认为第二个更容易阅读 你说的第二个代码有一个额外的赋值,无论如何都不是真的。公式的结果需要以两种代码存储到寄存器中。
编译代码后,额外变量的概念无效。例如,在您的例子中,编译器可以将
公式
存储在以前存储value1
或value2
的寄存器中,因为它们的生存期不重叠
如果第一个优化到第二个,我不会感到惊讶。我认为这种优化被称为“公共子表达式折叠”。但当然,只有在表达没有副作用的情况下才有可能
而且检查IL并不总是足以看到什么得到了优化。抖动也得到了优化。我有一些代码在IL中非常难看和缓慢,但在最终生成的x86代码中非常简短。当检查机器代码时,你需要确保它实际上是优化的。例如,如果您在VS中运行,即使发布代码没有完全优化
因此,我的猜测是,如果编译器能够优化它们,那么它们的速度同样快,另外,第二个更快,因为它不需要对公式求值两次。您必须反汇编字节码和/或基准来确定,但我认为这可能是相同的,因为编译器很容易看到
公式(在循环范围内)不会改变,可以很容易地直接“内联”(替换)
编辑:由于用户代码注释正确,分解字节码可能不够,因为优化可能只是在jitting之后才引入。OP没有询问哪种做法更好,但哪种更有效。是的,过早优化,诸如此类。我们明白了。这是否意味着我们不能讨论实际效率?是的,这只是一个例子,我所做的操作有点复杂和重复,在许多线程上,所以这对我来说很重要。+1表示硬数据。我不是一个憎恨者,只是厌倦了这些轻率的回答,它们不是答案。@harpo:不,事实上,你不能对实际效率进行有意义的讨论。获得实际效率的方法是在谨慎控制的条件下衡量绩效,正如Paul所做的那样。没有数据的扶手椅上的讨论毫无意义;这是在事实之前的理论,而不是从知识的立场。ra无法实现效率
static void MethodA()
{
for (int i = 0; i < 1000; i++) {
var value1 = getVal1fromSomeWhere();
var value2 = getVal2fromSomeWhere();
SendResultToA(value1 * value2 + value1 / value2);
SendResultToB(value1 * value2 + value1 / value2);
}
}
static void MethodB()
{
for (int i = 0; i < 1000; i++) {
var value1 = getVal1fromSomeWhere();
var value2 = getVal2fromSomeWhere();
var formula = value1 * value2 + value1 / value2;
SendResultToA(formula);
SendResultToB(formula);
}
}