简体   繁体   English

内部/外部循环中的变量声明

[英]variable declaration inside/outside loop

If for some reason I have to use as little memory space as possible, then is the second code bellow better that the first? 如果由于某种原因我不得不使用尽可能少的内存空间,那么第二个代码比第一个代码好吗? (the code is just for illustration and doesn't have any meaning). (该代码仅供参考,没有任何意义)。 (edit: imagine I want to make the assembly code of this before any optimization done by the JVM. Then do i use 99999998 extra memory locations in the first procedure compared to the second one? the focus is just one memory usage) (编辑:想象一下,我想在由JVM完成任何优化之前对此进行汇编代码。然后与第二个过程相比,我在第一个过程中是否使用了99999998个额外的内存位置?重点只是一个内存的使用)

First: 第一:

for(int i=0; i<99999999; i++){
    int k=2*i
}

Second: 第二:

int k=0;
for(int i=0; i<99999999; i++){
    k=2*i
}

What I'm sure of : 我确定的是:

In every case, The difference will not be visible. 在每种情况下,差异都不可见。 if you want to make such small optimization, Java is surely not the best technology. 如果要进行如此小的优化,那么Java当然不是最好的技术。 Which makes me recommend the first one cause it make the code more readable and logical. 这使我推荐第一个,因为它使代码更具可读性和逻辑性。 (Find it strange to declare a variable outside the for if you use it only inside it, it's confusing). (如果仅在变量内部使用for,则在变量外部声明变量会很奇怪,这很令人困惑)。


What I think : 我的想法:

In your small example and since your looking for a memory footprint. 在您的小示例中,并且您一直在寻找内存占用空间。 The first one is better because it follow the implicit rule mentioned in this comment : the smaller the scope is the better it is. 第一个更好,因为它遵循此注释中提到的隐式规则:范围越小越好。

In the first case the variable k is used only in a really small loop. 在第一种情况下,变量k仅在很小的循环中使用。 So the optimizer will easily understand it and use only a register, so no memory usage and less instructions. 因此,优化器将很容易理解它,并且仅使用寄存器,因此不占用内存,指令也更少。

In the second case, it will be harder for the optimizer to determine that k is not use elsewhere. 在第二种情况下,优化器将很难确定k在其他地方未使用。 So it could allow some memory instead of using a register. 因此,它可以允许一些内存而不是使用寄存器。 It will then use some memory and be less optimized since it will need instructions to load and store the memory. 然后,它将使用一些内存,并且优化程度较差,因为它将需要指令来加载和存储内存。

As mentionned in this comment , it will mostly depend on how you use it. 如本评论中所述 ,它主要取决于您的使用方式。 In your example the optimizer will detect it's the same usage in both case and will use no memory. 在您的示例中,优化器将在两种情况下都检测到相同的用法,并且不使用任何内存。 But in harder code it will not always find it. 但是在更难的代码中,它不会总是找到它。 So I recommend to have the smaller scope has possible. 所以我建议有较小范围的可能。

@pranay-khandelwal 's response links to an excellent discussion of this question in a different language. @ pranay-khandelwal的回复链接到用另一种语言对该问题的精彩讨论。 The Java JVM, however, throws bytecode around at runtime to try to achieve better performance, which can complicate things. 但是,Java JVM会在运行时抛出字节码,以尝试获得更好的性能,这会使事情复杂化。

There's actually another discussion here on a similar topic of in/out best practices in general for readability, which resulted in some benchmarks and discussion that one of the participants documented here 实际上关于可读性的进/出最佳实践的类似话题实际上还在这里进行了另一次讨论,从而产生了一些基准和讨论,其中一位参与者在此处进行了记录

As a general rule of thumb the second option will be better for memory and performance under almost all circumstances - where the former may be more self-documenting and maintainable, and avoid accidental use elsewhere in the outer scope. 作为一般经验法则,第二种选择在几乎所有情况下都将对内存和性能更好-在前一种情况下,前一种可能更具自文档性和可维护性,并避免在外部范围的其他地方意外使用。

Since you mention that the code in your post is only a representative example and this could apply to more than just simple types: 由于您提到帖子中的代码仅是一个代表性的示例,因此它不仅可以应用于简单类型,还可以应用于更多类型:

Replacing the contents of an already registered memory area is less costly than registering a new one and deregistering the old one (or waiting for it to be garbage collected) . 替换已经注册的存储区的内容要比注册一个新的存储区和取消注册旧的存储区(或等待它被垃圾回收)便宜。 Even where a language's compiler or interpreter smartly uses recently unreferenced things to store new things, that work also takes work, and is overhead that can optimistically be avoided with outer declarations - though as others mention, this is usually an unnecessary and potentially bug-spawning micro-optimization. 即使语言的编译器或解释器巧妙地使用最近未引用的内容来存储新内容, 工作也需要付出努力,并且开销可以通过外部声明来避免,尽管其他人提到,这通常是不必要的并且可能产生错误微观优化。

As from these short examples you provided, the second option. 从您提供的这些简短示例中,第二个选项。 However, it always depends on the logic of your code. 但是,它始终取决于代码的逻辑。 Thinking about performance and minimising execution space and time, the second code scales better even though it looks countering some good coding practices. 考虑性能并最大程度地减少执行空间和时间,第二个代码可扩展性更好,即使它看起来与某些良好的编码实践相反。 K in your code is used only inside the loop block. 代码中的K仅在循环块内使用。 However, it is "reused" over multiple "block iterations". 但是,它在多个“块迭代”中被“重用”。 Take a look at the syntax of your for loop , it declares i ( int i ) in the beginning of the statement; 看一下for循环的语法,它在语句的开头声明iint i ); this declaration will happen just once. 此声明只会发生一次。 Again, declaring the variable multiple times may lead to waste to time and memory. 同样,多次声明该变量可能会浪费时间和内存。 The JVM optimiser might do a good job in general, simple cases. 在一般的简单情况下,JVM优化器可能会做得很好。 However, it might fail in capturing the semantics of your code (Java). 但是,它可能无法捕获代码(Java)的语义。

for(int i=0,k=0; i<99999999; i++){
    k=2*i
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM