www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - __FILE__ and __LINE__ again...

reply "Paolo Invernizzi" <paolo.invernizzi gmail.com> writes:
Johannes Pfau wrote something like this, in the logger thread:

If you write code like this:

void log(string file = __FILE__)() //A template
{
   logImpl(file);
}
void logImpl(string file){} //Not a template

The compiler can always inline the log template. So there's no
template bloat as there will be effectively no instances of log.
Instead it will be inlined and logImpl will be called directly 
just as
if you manually called logImpl(__FILE__).
I'm trying something like that, but with __LINE__ in addition to put a little more pressure: void log(string file = __FILE__, int line = __LINE__)(){ logImpl(file, line); } void logImpl(string file, int line){} I've then compiled a single file filled with 'log()', but I've found from 'nm' that the text section is still full of templated functions. So the question is: is Johannes trick supposed to work, or there's something I don't understand well about template expansion and inlining? Thanks, Paolo
Sep 10 2013
next sibling parent "Dicebot" <public dicebot.lv> writes:
On Tuesday, 10 September 2013 at 16:00:55 UTC, Paolo Invernizzi 
wrote:
 Johannes Pfau wrote something like this, in the logger thread:

If you write code like this:

void log(string file = __FILE__)() //A template
{
  logImpl(file);
}
void logImpl(string file){} //Not a template

The compiler can always inline the log template. So there's no
template bloat as there will be effectively no instances of log.
Instead it will be inlined and logImpl will be called directly 
just as
if you manually called logImpl(__FILE__).
I'm trying something like that, but with __LINE__ in addition to put a little more pressure: void log(string file = __FILE__, int line = __LINE__)(){ logImpl(file, line); } void logImpl(string file, int line){} I've then compiled a single file filled with 'log()', but I've found from 'nm' that the text section is still full of templated functions. So the question is: is Johannes trick supposed to work, or there's something I don't understand well about template expansion and inlining? Thanks, Paolo
Johannes was wrong. DMD will always emit template symbols, even if those are completely inlined. Basically, anything that is somehow referenced in D modules gets into object file. Why won't you use default parameters in normal functions: void log(string file = __FILE__, int line = __LINE) { // ... } It uses caller context for token substitution, not declaration one.
Sep 10 2013
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Sep 10, 2013 at 06:00:53PM +0200, Paolo Invernizzi wrote:
 Johannes Pfau wrote something like this, in the logger thread:
 
If you write code like this:

void log(string file = __FILE__)() //A template
{
  logImpl(file);
}
void logImpl(string file){} //Not a template

The compiler can always inline the log template. So there's no
template bloat as there will be effectively no instances of log.
Instead it will be inlined and logImpl will be called directly
just as if you manually called logImpl(__FILE__).
I'm trying something like that, but with __LINE__ in addition to put a little more pressure: void log(string file = __FILE__, int line = __LINE__)(){ logImpl(file, line); } void logImpl(string file, int line){} I've then compiled a single file filled with 'log()', but I've found from 'nm' that the text section is still full of templated functions. So the question is: is Johannes trick supposed to work, or there's something I don't understand well about template expansion and inlining?
[...] Did you compile with dmd -inline? Having said that, if you don't have variadic arguments, __FILE__ and __LINE__ should be default arguments at the end of the *runtime* argument list. Runtime arguments should be used to prevent template bloat: void log(/* other arguments here */, string file=__FILE__, int line=__LINE__) { ... } If you have variadic arguments, though, this wouldn't work. In any case, if the template function is just a thin wrapper around logImpl, and you're compiling with -inline, then there should be no runtime overhead. The compiler will still emit template instantiations for each call to log(), but you can get rid of this with link-time optimization (on Posix, you'd add -L-gc-sections to your dmd command-line: this will cause ld to delete code sections that are never referenced, which includes the log() instantiations if indeed they have been inlined). T -- Arise, you prisoners of Windows Arise, you slaves of Redmond, Wash, The day and hour soon are coming When all the IT folks say "Gosh!" It isn't from a clever lawsuit That Windowsland will finally fall, But thousands writing open source code Like mice who nibble through a wall. -- The Linux-nationale by Greg Baker
Sep 10 2013
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 10 September 2013 at 16:45:33 UTC, H. S. Teoh wrote:
 but you can get rid of this with link-time
 optimization (on Posix, you'd add -L-gc-sections to your dmd
 command-line: this will cause ld to delete code sections that 
 are never
 referenced, which includes the log() instantiations if indeed 
 they have
 been inlined).
Using `--gc-sections` requires each function and data item to be placed into its own section (-fdata-sections and -ffunction-sections in gcc). AFAIK dmd does not do it.
Sep 10 2013
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Sep 10, 2013 at 06:50:03PM +0200, Dicebot wrote:
 On Tuesday, 10 September 2013 at 16:45:33 UTC, H. S. Teoh wrote:
but you can get rid of this with link-time optimization (on Posix,
you'd add -L-gc-sections to your dmd command-line: this will cause ld
to delete code sections that are never referenced, which includes the
log() instantiations if indeed they have been inlined).
Using `--gc-sections` requires each function and data item to be placed into its own section (-fdata-sections and -ffunction-sections in gcc). AFAIK dmd does not do it.
Hmm. Does that mean gdc supports that, then? T -- People tell me I'm stubborn, but I refuse to accept it!
Sep 10 2013
next sibling parent "Dicebot" <public dicebot.lv> writes:
On Tuesday, 10 September 2013 at 16:58:54 UTC, H. S. Teoh wrote:
 On Tue, Sep 10, 2013 at 06:50:03PM +0200, Dicebot wrote:
 On Tuesday, 10 September 2013 at 16:45:33 UTC, H. S. Teoh 
 wrote:
but you can get rid of this with link-time optimization (on 
Posix,
you'd add -L-gc-sections to your dmd command-line: this will 
cause ld
to delete code sections that are never referenced, which 
includes the
log() instantiations if indeed they have been inlined).
Using `--gc-sections` requires each function and data item to be placed into its own section (-fdata-sections and -ffunction-sections in gcc). AFAIK dmd does not do it.
Hmm. Does that mean gdc supports that, then? T
Well, it definitely _can_ support it, but we should ask Iain if it actually supports it :) Gonna try and experiment with it a bit.
Sep 10 2013
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Tuesday, 10 September 2013 at 16:58:54 UTC, H. S. Teoh wrote:
 On Tue, Sep 10, 2013 at 06:50:03PM +0200, Dicebot wrote:
 On Tuesday, 10 September 2013 at 16:45:33 UTC, H. S. Teoh 
 wrote:
but you can get rid of this with link-time optimization (on 
Posix,
you'd add -L-gc-sections to your dmd command-line: this will 
cause ld
to delete code sections that are never referenced, which 
includes the
log() instantiations if indeed they have been inlined).
Using `--gc-sections` requires each function and data item to be placed into its own section (-fdata-sections and -ffunction-sections in gcc). AFAIK dmd does not do it.
Hmm. Does that mean gdc supports that, then?
Actually I was wrong, looks like DMD does section differentiation by default. I am wondering if --gc-sections should be made default on Linux targets...
Sep 12 2013
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Sep 12, 2013 at 03:37:58PM +0200, Dicebot wrote:
 On Tuesday, 10 September 2013 at 16:58:54 UTC, H. S. Teoh wrote:
On Tue, Sep 10, 2013 at 06:50:03PM +0200, Dicebot wrote:
On Tuesday, 10 September 2013 at 16:45:33 UTC, H. S. Teoh wrote:
but you can get rid of this with link-time optimization (on Posix,
you'd add -L-gc-sections to your dmd command-line: this will cause
ld to delete code sections that are never referenced, which
includes the log() instantiations if indeed they have been
inlined).
Using `--gc-sections` requires each function and data item to be placed into its own section (-fdata-sections and -ffunction-sections in gcc). AFAIK dmd does not do it.
Hmm. Does that mean gdc supports that, then?
Actually I was wrong, looks like DMD does section differentiation by default. I am wondering if --gc-sections should be made default on Linux targets...
Interesting. However, I ran into some runtime segfaults caused by --gc-sections yesterday. I didn't investigate further, but that makes me hesitant to make --gc-sections the default. Something, somewhere, is being broken by --gc-sections. It doesn't happen in all cases, though. Only some of my programs are affected by it. I should investigate this when I get some time. T -- Let's call it an accidental feature. -- Larry Wall
Sep 12 2013
parent "Dicebot" <public dicebot.lv> writes:
On Thursday, 12 September 2013 at 13:58:03 UTC, H. S. Teoh wrote:
 Interesting. However, I ran into some runtime segfaults caused 
 by
 --gc-sections yesterday. I didn't investigate further, but that 
 makes me
 hesitant to make --gc-sections the default. Something, 
 somewhere, is
 being broken by --gc-sections. It doesn't happen in all cases, 
 though.
 Only some of my programs are affected by it.

 I should investigate this when I get some time.
Actually, nevermind, dmd only does it for small portion of the code :) However, I have tested -ffunction-sections + -fdata-sections + --gc-sections on gdc and have reduced binary size _twice_ for a simple `writeln(arr.map(a => a*2)())` snippet. Which is only partially cool because gdc binary is more than twice larger than dmd one for same code :D Problem with --gc-sections is that it can't be used when building libraries and any with executable that expose parts of own code to shared libraries. It is essentially a whole program optimization and it can't be done without compiler support in cases where binary is _not_ the whole program.
Sep 12 2013
prev sibling parent "Paolo Invernizzi" <paolo.invernizzi gmail.com> writes:
On Tuesday, 10 September 2013 at 16:45:33 UTC, H. S. Teoh wrote:
 On Tue, Sep 10, 2013 at 06:00:53PM +0200, Paolo Invernizzi 
 wrote:
 Johannes Pfau wrote something like this, in the logger thread:
 
If you write code like this:

void log(string file = __FILE__)() //A template
{
  logImpl(file);
}
void logImpl(string file){} //Not a template

The compiler can always inline the log template. So there's no
template bloat as there will be effectively no instances of 
log.
Instead it will be inlined and logImpl will be called directly
just as if you manually called logImpl(__FILE__).
I'm trying something like that, but with __LINE__ in addition to put a little more pressure: void log(string file = __FILE__, int line = __LINE__)(){ logImpl(file, line); } void logImpl(string file, int line){} I've then compiled a single file filled with 'log()', but I've found from 'nm' that the text section is still full of templated functions. So the question is: is Johannes trick supposed to work, or there's something I don't understand well about template expansion and inlining?
[...] Did you compile with dmd -inline? Having said that, if you don't have variadic arguments, __FILE__ and __LINE__ should be default arguments at the end of the *runtime* argument list. Runtime arguments should be used to prevent template bloat: void log(/* other arguments here */, string file=__FILE__, int line=__LINE__) { ... } If you have variadic arguments, though, this wouldn't work. In any case, if the template function is just a thin wrapper around logImpl, and you're compiling with -inline, then there should be no runtime overhead. The compiler will still emit template instantiations for each call to log(), but you can get rid of this with link-time optimization (on Posix, you'd add -L-gc-sections to your dmd command-line: this will cause ld to delete code sections that are never referenced, which includes the log() instantiations if indeed they have been inlined). T
Thank you to everybody, As you can guess, I would like to have variadic arguments: I'll try to investigate if some mixin syntax is not too horrible to be use... /Paolo
Sep 10 2013