Lazy eval -- an example issue
kris
foo at bar.com
Wed Aug 23 11:50:44 PDT 2006
John Reimer wrote:
> On Wed, 23 Aug 2006 00:33:08 -0700, Paolo Invernizzi
> <arathorn at NOSPAM_fastwebnet.it> wrote:
>
>> kris wrote:
>>
>>> Walter Bright wrote:
>>>
>>>> kris wrote:
>>>>
>>>>> Can't do that; the char[] version have to stay.
>>>>
>>>>
>>>>
>>>> Why?
>>>
>>> Because my Boss says so
>>
>>
>> kris, really, is it a joke?
>>
>> If not, and I'm supposing you are using the mango logging package in
>> some big D application, can you post us the performance difference
>> you have noticed using the char[] version versus the delegate version?
>>
>> ---
>> Paolo Invernizzi
>
>
>
> I think he was being sarcastic.
>
> -JJR
No sarcasm required. The recent development of deliberately introducing
ambiguity into the language warrants serious concern. It's something
that should, and does, trouble most of us quite deeply (judging by the
responses).
As for performance differences, I suspect you're missing the bigger
picture, Paolo? I'll try to draw one: you may have noticed my concern
about delegates and heap-based frames? If so, you'll probably have seen
a reponse from Walter noting that specific types of expr can probably be
identified as not escaping the hosting function? There's a gaping hole
in that marketing-style claim, and you should treat it with a heathly
dose of suspicion.
For example; I'd like to use delegates as a nice clean shortcut for
logging. Instead of writing
# if (log.enabled (log.Trace))
# log.trace (sprint ("my log message %d, %s", i, s));
I'd instead like to write this
# log.trace ({return sprint ("my log message %d, %s", i, s);});
Makes sense, right? We don't want to invoke the cost of the sprint()
function unless tracing is enabled. Note that these are guaranteed to be
synchronous callbacks. The delegates are not "saved for later" like a
gui delegate might be. Thus, the frame of the hosting function should be
stack-based.
However, because the callback references local variables, there's no
guarantee the host-frame will not be allocated on the heap instead. This
is the issue we'd been trying to address in another thread. Namely, if
there's going to be ambiguity over whether a delegate is invoked
syncrhonously or asynchronously, we probably need a way to tell the
compiler what's what (rather than let it make the wrong choice).
In simplistic terms, if I have a function like so (note that there's no
delegate intended here):
# real somefunk (real x, real y)
# {
# if (x is real.nan || y is real.nan)
# log.error (sprint ("invalid args %s, %s", x, y));
#
# // do something with x & y
# }
It's quite possible that the frame for this will be heap-allocated, even
though the logger invocation is not intending to use delegates at all.
The damn compiler might go and turn the char[] expr into a sneaky
delegate, and then decide it needs a heap-frame instead of a stack one.
That, my friend, is a serious performance issue (heap allocation each
and every time somefunk() is called), and it's all hidden behind a plush
blue-velvet curtain.
Supposing we actually *want* to use a delegate in this situation? e.g.
# real somefunk (real x, real y)
# {
# if (x is real.nan || y is real.nan)
# log.error ({return sprint ("invalid args %s, %s", x, y);});
#
# // do something with x & y
# }
We still need some manner in which to tell the compiler that the
callback is synchronous, rather than asynchronous, and that it should
not be trying to allocate a heap-frame for this function. Again, this is
what the other thread was discussing in depth. One of the ideas
put-forward there was to somehow mark the hosting function as being a
synchronous-host; something like this
# scope real somefunk (real x, real y);
Another opinion was to mark the /usage/ of the delegate itself, the
logger in this case, with something akin to the following
# void error (scope char[] delegate());
Each of these have their relative pros and cons. What *is* evident, is
that the compiler cannot be trusted to make the appropriate decision. In
contrast, it's quite likely to make a highly conservative, and very
poor, decision. Implied behaviour is often entirely the wrong thing to
do and, without a means for manual control, will quickly become a most
serious problem.
I hope you can see where the recent ambiguities lead to? You can easily
wind up with unexpected (and unwanted) delegates, which may well lead to
unexpected (and unwanted) heap-based frames. To resolve, the ambiguities
must be removed. Additionally, some *dependable* mechanism should be put
in place to manage (or override) how & when heap-based frames are
allocated.
More information about the Digitalmars-d
mailing list