www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Block statements and memory management

reply Murilo <murilomiranda92 hotmail.com> writes:
Does anyone know if when I create a variable inside a scope as in
{int a = 10;}
it disappears complete from the memory when the scope finishes? 
Or does it remain in some part of the memory? I am thinking of 
using scopes to make optimized programs that consume less memory.
Mar 15 2019
next sibling parent Paul Backus <snarwin gmail.com> writes:
On Saturday, 16 March 2019 at 03:47:43 UTC, Murilo wrote:
 Does anyone know if when I create a variable inside a scope as 
 in
 {int a = 10;}
 it disappears complete from the memory when the scope finishes? 
 Or does it remain in some part of the memory? I am thinking of 
 using scopes to make optimized programs that consume less 
 memory.
It depends on how the compiler translates and optimizes the code. An integer variable like `a` in your example might never exist in memory at all, if the compiler can allocate a register for it until it goes out of scope. The easiest way to find out is to look at a disassembly of the compiled code.
Mar 15 2019
prev sibling next sibling parent Meta <jared771 gmail.com> writes:
On Saturday, 16 March 2019 at 03:47:43 UTC, Murilo wrote:
 Does anyone know if when I create a variable inside a scope as 
 in
 {int a = 10;}
 it disappears complete from the memory when the scope finishes? 
 Or does it remain in some part of the memory? I am thinking of 
 using scopes to make optimized programs that consume less 
 memory.
I'd recommend against these sorts of micro-optimizations. Compilers are every good at doing this kind of thing manually so you don't have to worry about it and can concentrate on the actual logic of your program.
Mar 15 2019
prev sibling next sibling parent reply Dennis <dkorpel gmail.com> writes:
On Saturday, 16 March 2019 at 03:47:43 UTC, Murilo wrote:
 Does anyone know if when I create a variable inside a scope as 
 in
 {int a = 10;}
 it disappears complete from the memory when the scope finishes? 
 Or does it remain in some part of the memory? I am thinking of 
 using scopes to make optimized programs that consume less 
 memory.
In general, you want variables to have no larger scope than needed, so in large functions reducing the scope may be useful. When it comes to efficiency however, doing that is neither necessary nor sufficient for the compiler to re-use registers / stack space. I looked at the assembly output of DMD for this: ``` void func(int a); void main() { { int a = 2; func(a); } { int b = 3; func(b); } } ``` Without optimizations (the -O flag), it stores a and b on different places in the stack. With optimizations, the values of a and b (2 and 3) are simply loaded in the EDI register before the call. Removing the braces doesn't change anything about that. The compiler does live variable analysis [1] as well as data-flow analysis [2] to figure out that it's only needed to load the values 2 and 3 just before the function call. This is just a trivial example, but the same applies to larger functions. In any case, for better memory efficiency I'd consider looking at reducing dynamic allocations such as new or malloc. Memory on the stack is basically free compared to that, so even if adding lots of braces to your code reduces stack memory, chances are it's a low leverage point. [1] https://en.wikipedia.org/wiki/Live_variable_analysis [2] https://en.wikipedia.org/wiki/Data-flow_analysis
Mar 16 2019
next sibling parent spir <denis.spir gmail.com> writes:
On 16/03/2019 11:19, Dennis via Digitalmars-d-learn wrote:
 On Saturday, 16 March 2019 at 03:47:43 UTC, Murilo wrote:
 Does anyone know if when I create a variable inside a scope as in
 {int a = 10;}
 it disappears complete from the memory when the scope finishes? Or does it 
 remain in some part of the memory? I am thinking of using scopes to make 
 optimized programs that consume less memory.
In general, you want variables to have no larger scope than needed, so in large functions reducing the scope may be useful. When it comes to efficiency however, doing that is neither necessary nor sufficient for the compiler to re-use registers / stack space. I looked at the assembly output of DMD for this: ``` void func(int a); void main() {     {     int a = 2;     func(a);     }     {     int b = 3;     func(b);     } } ``` Without optimizations (the -O flag), it stores a and b on different places in the stack. With optimizations, the values of a and b (2 and 3) are simply loaded in the EDI register before the call. Removing the braces doesn't change anything about that. The compiler does live variable analysis [1] as well as data-flow analysis [2] to figure out that it's only needed to load the values 2 and 3 just before the function call. This is just a trivial example, but the same applies to larger functions. In any case, for better memory efficiency I'd consider looking at reducing dynamic allocations such as new or malloc. Memory on the stack is basically free compared to that, so even if adding lots of braces to your code reduces stack memory, chances are it's a low leverage point. [1] https://en.wikipedia.org/wiki/Live_variable_analysis [2] https://en.wikipedia.org/wiki/Data-flow_analysis
Just to add a bit on what has been said: * Register allocation (see wikipedia) is a well-researched area. * By coding that way, you force the compiler to optimise *a certain way* which may prevent it to perform other, more relevant optimisations. * You cannot beat the knowledge in that domain, it is simply too big and complex, just be confident. diniz
Mar 16 2019
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Mar 16, 2019 at 01:21:02PM +0100, spir via Digitalmars-d-learn wrote:
 On 16/03/2019 11:19, Dennis via Digitalmars-d-learn wrote:
[...]
 In any case, for better memory efficiency I'd consider looking at
 reducing dynamic allocations such as new or malloc. Memory on the
 stack is basically free compared to that, so even if adding lots of
 braces to your code reduces stack memory, chances are it's a low
 leverage point.
 
 [1] https://en.wikipedia.org/wiki/Live_variable_analysis
 [2] https://en.wikipedia.org/wiki/Data-flow_analysis
Just to add a bit on what has been said: * Register allocation (see wikipedia) is a well-researched area. * By coding that way, you force the compiler to optimise *a certain way* which may prevent it to perform other, more relevant optimisations. * You cannot beat the knowledge in that domain, it is simply too big and complex, just be confident.
[...] And to add even more to that: before embarking on micro-optimizations of this sort, always check with a profiler whether or not the bottleneck is even in that part of the code. Often I find myself very surprised at where the real bottleneck is, which is often nowhere near where I thought it should be. Also, check with a memory profiler to find out where the real heavy memory usage points are. It may not be where you thought it was. Generally speaking, in this day and age of highly-optimizing compilers, premature optimization is the root of all evils, because it uglifies your code and makes it hard to maintain for little or no gain, and sometimes for *negative* gain, because by writing code in an unusual way, you confuse the optimizer as to your real intent, thereby reducing its effectiveness at producing optimized code. Don't optimize until you have verified with a profiler where your bottlenecks are. It takes a lot of time and effort to write code this way, so make it count by applying it where it actually matters. Of course, this assumes you use a compiler with a powerful-enough optimizer. I recommend ldc/gdc if performance is important to you. Dmd compiles somewhat faster, but at the cost of poorer codegen. T -- The early bird gets the worm. Moral: ewww...
Mar 16 2019
prev sibling parent reply Johan Engelen <j j.nl> writes:
On Saturday, 16 March 2019 at 03:47:43 UTC, Murilo wrote:
 Does anyone know if when I create a variable inside a scope as 
 in
 {int a = 10;}
 it disappears complete from the memory when the scope finishes? 
 Or does it remain in some part of the memory? I am thinking of 
 using scopes to make optimized programs that consume less 
 memory.
Others have made good points in this thread, but what is missing is that indeed scopes _can_ be used beneficially to reduce memory footprint. I recommend playing with this code on d.godbolt.org: ``` void func(ref int[10] a); // important detail: pointer void foo() { { int[10] a; func(a); } { int[10] b; func(b); } } ``` Because the variable is passed by reference (pointer), the optimizer cannot merge the storage space of `a` and `b` _unless_ scope information is taken into account. Without taking scope into account, the first `func` call could store the pointer to `a` somewhere for later use in the second `func` call for example. However, because of scope, using `a` after its scope has ended is UB, and thus variables `a` and `b` can be used. GDC uses scope information for variable lifetime optimization, but LDC and DMD both do not. For anyone interested in working on compilers: adding variable scope lifetime to LDC (not impossibly hard) would be a nice project and be very valuable. -Johan
Mar 16 2019
parent Murilo <murilomiranda92 hotmail.com> writes:
On Saturday, 16 March 2019 at 15:53:26 UTC, Johan Engelen wrote:
 On Saturday, 16 March 2019 at 03:47:43 UTC, Murilo wrote:
 Does anyone know if when I create a variable inside a scope as 
 in
 {int a = 10;}
 it disappears complete from the memory when the scope 
 finishes? Or does it remain in some part of the memory? I am 
 thinking of using scopes to make optimized programs that 
 consume less memory.
Others have made good points in this thread, but what is missing is that indeed scopes _can_ be used beneficially to reduce memory footprint. -Johan
I would like to thank everyone for your help, those informations were very helpful.
Apr 05 2019