www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - are scope guards (scope(exit, success,

reply Timothee Cour <thelastmammoth gmail.com> writes:
I'm curious whether scope guards add any cost over the naive way, eg:

```
void fun(){
  ...
  scope(success) {bar;}
  ...
}
```

vs:

```
void fun(){
  ...
  if(foo1){
    bar;  // add this before each return
    return;
  }
  ...
  bar;
  return;
}
```

For scope(success) and scope(failure), the naive way would anyway
involve try/catch statements but what about scope(exit)? Does the
zero-cost exception model (zero cost being for non-thrown exceptions)
guarantee us that scope(success) has 0 overhead over naive way?
Feb 08 2018
parent reply Mike Parker <aldacron gmail.com> writes:
On Thursday, 8 February 2018 at 10:09:12 UTC, Timothee Cour wrote:
 I'm curious whether scope guards add any cost over the naive 
 way, eg:

 ```
 void fun(){
   ...
   scope(success) {bar;}
   ...
 }
 ```

 vs:

 ```
 void fun(){
   ...
   if(foo1){
     bar;  // add this before each return
     return;
   }
   ...
   bar;
   return;
 }
 ```

 For scope(success) and scope(failure), the naive way would 
 anyway
 involve try/catch statements but what about scope(exit)? Does 
 the
 zero-cost exception model (zero cost being for non-thrown 
 exceptions)
 guarantee us that scope(success) has 0 overhead over naive way?
Scope guards are lowered to the equivalent try/catch/finally blocks anyway.
Feb 08 2018
next sibling parent Timothee Cour <thelastmammoth gmail.com> writes:
I know that, my question is whether it adds any runtime overhead over
naive way (which is to call the "bar" finalizer before each return
statement)  in the case where no exception is thrown


On Thu, Feb 8, 2018 at 2:44 AM, Mike Parker via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:
 On Thursday, 8 February 2018 at 10:09:12 UTC, Timothee Cour wrote:
 I'm curious whether scope guards add any cost over the naive way, eg:

 ```
 void fun(){
   ...
   scope(success) {bar;}
   ...
 }
 ```

 vs:

 ```
 void fun(){
   ...
   if(foo1){
     bar;  // add this before each return
     return;
   }
   ...
   bar;
   return;
 }
 ```

 For scope(success) and scope(failure), the naive way would anyway
 involve try/catch statements but what about scope(exit)? Does the
 zero-cost exception model (zero cost being for non-thrown exceptions)
 guarantee us that scope(success) has 0 overhead over naive way?
Scope guards are lowered to the equivalent try/catch/finally blocks anyway.
Feb 08 2018
prev sibling next sibling parent reply Daniel Kozak <kozzi11 gmail.com> writes:
I mean scope(success), for scope(exit) there is no speed penalty

On Thu, Feb 8, 2018 at 12:03 PM, Daniel Kozak <kozzi11 gmail.com> wrote:

 Yes, it add, but is almost zero

 On Thu, Feb 8, 2018 at 12:00 PM, Timothee Cour via Digitalmars-d-learn <
 digitalmars-d-learn puremagic.com> wrote:

 I know that, my question is whether it adds any runtime overhead over
 naive way (which is to call the "bar" finalizer before each return
 statement)  in the case where no exception is thrown


 On Thu, Feb 8, 2018 at 2:44 AM, Mike Parker via Digitalmars-d-learn
 <digitalmars-d-learn puremagic.com> wrote:
 On Thursday, 8 February 2018 at 10:09:12 UTC, Timothee Cour wrote:
 I'm curious whether scope guards add any cost over the naive way, eg:

 ```
 void fun(){
   ...
   scope(success) {bar;}
   ...
 }
 ```

 vs:

 ```
 void fun(){
   ...
   if(foo1){
     bar;  // add this before each return
     return;
   }
   ...
   bar;
   return;
 }
 ```

 For scope(success) and scope(failure), the naive way would anyway
 involve try/catch statements but what about scope(exit)? Does the
 zero-cost exception model (zero cost being for non-thrown exceptions)
 guarantee us that scope(success) has 0 overhead over naive way?
Scope guards are lowered to the equivalent try/catch/finally blocks
anyway.
Feb 08 2018
parent Seb <seb wilzba.ch> writes:
On Thursday, 8 February 2018 at 11:23:43 UTC, Daniel Kozak wrote:
 I mean scope(success), for scope(exit) there is no speed penalty

 On Thu, Feb 8, 2018 at 12:03 PM, Daniel Kozak 
 <kozzi11 gmail.com> wrote:

 Yes, it add, but is almost zero

 On Thu, Feb 8, 2018 at 12:00 PM, Timothee Cour via 
 Digitalmars-d-learn < digitalmars-d-learn puremagic.com> wrote:

 I know that, my question is whether it adds any runtime 
 overhead over naive way (which is to call the "bar" finalizer 
 before each return statement)  in the case where no exception 
 is thrown


 On Thu, Feb 8, 2018 at 2:44 AM, Mike Parker via 
 Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:
 On Thursday, 8 February 2018 at 10:09:12 UTC, Timothee Cour 
 wrote:
 I'm curious whether scope guards add any cost over the 
 naive way, eg:

 ```
 void fun(){
   ...
   scope(success) {bar;}
   ...
 }
 ```

 vs:

 ```
 void fun(){
   ...
   if(foo1){
     bar;  // add this before each return
     return;
   }
   ...
   bar;
   return;
 }
 ```

 For scope(success) and scope(failure), the naive way would 
 anyway
 involve try/catch statements but what about scope(exit)? 
 Does the
 zero-cost exception model (zero cost being for non-thrown 
 exceptions)
 guarantee us that scope(success) has 0 overhead over naive 
 way?
Scope guards are lowered to the equivalent try/catch/finally blocks
anyway.
Yes, it's easy to see this when looking at the lowered AST and ASM. 1) AST https://run.dlang.io/is/KNJbnP --- import object; import core.stdc.stdio; void main() { printf("%s", "All good."); printf("%s", "FOO"); return 0; } --- 2) ASM https://run.dlang.io/is/bIVYvi --- _Dmain: push RBP mov RBP,RSP lea RSI,FLAT:.rodata[00h][RIP] lea RDI,FLAT:.rodata[00h][RIP] xor EAX,EAX call printf PLT32 lea RSI,FLAT:.rodata[00h][RIP] lea RDI,FLAT:.rodata[00h][RIP] xor EAX,EAX call printf PLT32 xor EAX,EAX pop RBP ret ---
Feb 08 2018
prev sibling next sibling parent Daniel Kozak <kozzi11 gmail.com> writes:
Yes, it add, but is almost zero

On Thu, Feb 8, 2018 at 12:00 PM, Timothee Cour via Digitalmars-d-learn <
digitalmars-d-learn puremagic.com> wrote:

 I know that, my question is whether it adds any runtime overhead over
 naive way (which is to call the "bar" finalizer before each return
 statement)  in the case where no exception is thrown


 On Thu, Feb 8, 2018 at 2:44 AM, Mike Parker via Digitalmars-d-learn
 <digitalmars-d-learn puremagic.com> wrote:
 On Thursday, 8 February 2018 at 10:09:12 UTC, Timothee Cour wrote:
 I'm curious whether scope guards add any cost over the naive way, eg:

 ```
 void fun(){
   ...
   scope(success) {bar;}
   ...
 }
 ```

 vs:

 ```
 void fun(){
   ...
   if(foo1){
     bar;  // add this before each return
     return;
   }
   ...
   bar;
   return;
 }
 ```

 For scope(success) and scope(failure), the naive way would anyway
 involve try/catch statements but what about scope(exit)? Does the
 zero-cost exception model (zero cost being for non-thrown exceptions)
 guarantee us that scope(success) has 0 overhead over naive way?
Scope guards are lowered to the equivalent try/catch/finally blocks
anyway.
Feb 08 2018
prev sibling parent Seb <seb wilzba.ch> writes:
On Thursday, 8 February 2018 at 10:44:37 UTC, Mike Parker wrote:
 On Thursday, 8 February 2018 at 10:09:12 UTC, Timothee Cour 
 wrote:
 I'm curious whether scope guards add any cost over the naive 
 way, eg:

 ```
 void fun(){
   ...
   scope(success) {bar;}
   ...
 }
 ```

 vs:

 ```
 void fun(){
   ...
   if(foo1){
     bar;  // add this before each return
     return;
   }
   ...
   bar;
   return;
 }
 ```

 For scope(success) and scope(failure), the naive way would 
 anyway
 involve try/catch statements but what about scope(exit)? Does 
 the
 zero-cost exception model (zero cost being for non-thrown 
 exceptions)
 guarantee us that scope(success) has 0 overhead over naive way?
Scope guards are lowered to the equivalent try/catch/finally blocks anyway.
Yes, let's look at it: ``` scope(failure) printf("%s", "error".ptr); printf("%s", "All good.".ptr); ``` 1) Lowered AST https://run.dlang.io/is/PmRfkb --- import object; import core.stdc.stdio; void main() { try { printf("%s", "All good."); } catch(Throwable __o2) { printf("%s", "error"); throw __o2; } return 0; } --- 2) Assembly (reduced to the interesting bits - see https://run.dlang.io/is/Cafgja for the full ASM) --- call printf PLT32 jmp short L69 lea RSP,0FFFFFFF0h[RBP] mov -8[RBP],EDX mov RDI,RAX call __dmd_begin_catch PLT32 mov -010h[RBP],RAX mov EAX,-8[RBP] cmp EAX,1 je L3F jmp short L62 L3F: lea RSI,FLAT:.rodata[00h][RIP] lea RDI,FLAT:.rodata[00h][RIP] xor EAX,EAX call printf PLT32 mov RDI,-010h[RBP] call _d_throwdwarf PLT32 mov RSP,RBP pop RBP ret ---
Feb 08 2018