zsh-users
 help / color / mirror / code / Atom feed
* Nested function definition question
@ 2019-07-16  8:43 Nick Cross
  2019-07-16 14:13 ` Ray Andrews
  0 siblings, 1 reply; 6+ messages in thread
From: Nick Cross @ 2019-07-16  8:43 UTC (permalink / raw)
  To: zsh-users


Hi,

If I have some functions e.g.

common() {
BAR=1
}

foo() {
common
....
}

Is there a way of 'inlining' the definition of common in foo so that I 
don't have to call it each time? ( but the source can still be separated 
out for maintenance purposes )

Thanks

Nick


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Nested function definition question
  2019-07-16  8:43 Nested function definition question Nick Cross
@ 2019-07-16 14:13 ` Ray Andrews
  2019-07-16 14:44   ` Nick Cross
  0 siblings, 1 reply; 6+ messages in thread
From: Ray Andrews @ 2019-07-16 14:13 UTC (permalink / raw)
  To: zsh-users

On 2019-07-16 1:43 a.m., Nick Cross wrote:
>
>
> Is there a way of 'inlining' the definition of common in foo so that I 
> don't have to call it each time? ( but the source can still be 
> separated out for maintenance purposes )
>
Why would you want to?  It's interpreted so there'd be almost no 
difference in speed even if you did actually inline it, no?  Mind I 
suppose if 'common()' was autoloaded there might be a microsecond 
improvement but.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Nested function definition question
  2019-07-16 14:13 ` Ray Andrews
@ 2019-07-16 14:44   ` Nick Cross
  2019-07-17  5:49     ` Roman Perepelitsa
  0 siblings, 1 reply; 6+ messages in thread
From: Nick Cross @ 2019-07-16 14:44 UTC (permalink / raw)
  To: Ray Andrews, zsh-users

On 16/07/2019 15:13, Ray Andrews wrote:
> On 2019-07-16 1:43 a.m., Nick Cross wrote:
>>
>>
>> Is there a way of 'inlining' the definition of common in foo so that I
>> don't have to call it each time? ( but the source can still be
>> separated out for maintenance purposes )
>>
> Why would you want to?  It's interpreted so there'd be almost no
> difference in speed even if you did actually inline it, no?  Mind I
> suppose if 'common()' was autoloaded there might be a microsecond
> improvement but.
> 
> 

I realise its interpreted and it makes little or no difference, it was 
more out of curiosity ;-)

Nick

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Nested function definition question
  2019-07-16 14:44   ` Nick Cross
@ 2019-07-17  5:49     ` Roman Perepelitsa
  2019-07-17  9:34       ` Nick Cross
  0 siblings, 1 reply; 6+ messages in thread
From: Roman Perepelitsa @ 2019-07-17  5:49 UTC (permalink / raw)
  To: Nick Cross; +Cc: Ray Andrews, Zsh Users

On Tue, Jul 16, 2019 at 4:45 PM Nick Cross <zsh@goots.org> wrote:
>
> I realise its interpreted and it makes little or no difference, it was
> more out of curiosity ;-)

Inlining functions makes a big difference because function calls are
very expensive in ZSH. Calling a function to do something trivial
takes ~10 times longer than doing the same thing inline.

Roman.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Nested function definition question
  2019-07-17  5:49     ` Roman Perepelitsa
@ 2019-07-17  9:34       ` Nick Cross
  2019-07-17  9:54         ` Roman Perepelitsa
  0 siblings, 1 reply; 6+ messages in thread
From: Nick Cross @ 2019-07-17  9:34 UTC (permalink / raw)
  To: Roman Perepelitsa, Nick Cross; +Cc: Ray Andrews, Zsh Users

On 17/07/2019 06:49, Roman Perepelitsa wrote:
> On Tue, Jul 16, 2019 at 4:45 PM Nick Cross <zsh@goots.org> wrote:
>>
>> I realise its interpreted and it makes little or no difference, it was
>> more out of curiosity ;-)
> 
> Inlining functions makes a big difference because function calls are
> very expensive in ZSH. Calling a function to do something trivial
> takes ~10 times longer than doing the same thing inline.
> 
> Roman.
> 

Really? Thats interesting. Is there any benchmarks available showing 
this? So is it actually possible to do this?

Nick

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Nested function definition question
  2019-07-17  9:34       ` Nick Cross
@ 2019-07-17  9:54         ` Roman Perepelitsa
  0 siblings, 0 replies; 6+ messages in thread
From: Roman Perepelitsa @ 2019-07-17  9:54 UTC (permalink / raw)
  To: Nick Cross; +Cc: Ray Andrews, Zsh Users

On Wed, Jul 17, 2019 at 11:35 AM Nick Cross <zsh@goots.org> wrote:
>
> On 17/07/2019 06:49, Roman Perepelitsa wrote:
> > Inlining functions makes a big difference because function calls are
> > very expensive in ZSH. Calling a function to do something trivial
> > takes ~10 times longer than doing the same thing inline.
>
> Really? Thats interesting. Is there any benchmarks available showing
> this?

Here's a quick one:

    local -i c=0

    function inc() { ((++c)) }

    function outofline() {
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
     inc; inc; inc; inc;
    }

    function inline() {
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
     ((++c)); ((++c)); ((++c)); ((++c));
    }

    time ( repeat 10000 outofline )
    time ( repeat 10000 inline )

I've got:

  ( repeat 10000; do; outofline; done; )  cpu 4.184 total
  ( repeat 10000; do; inline; done; )  cpu 0.171 total

Apparently, ((++c)) is 24 times faster than a call to function that
does the same thing. You can adapt this benchmark to measure something
closer to what you care about.

> So is it actually possible to do this?

It's definitely possible to inline functions by hand the same way I
did in the benchmark.

Another thing that can make a difference is manual loop unrolling,
although the overhead of looping isn't as big as that of function
calls. That is, you can replace this:

    function normal() {
     local -i i c
     for ((i = 0; i != 6400000; ++i)); do
       ((++c))
     done
    }

With this:

    function unrolled() {
     local -i i c
     for ((i = 0; i != 6400000; i+=64)); do
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
       ((++c)); ((++c)); ((++c)); ((++c));
     done
    }

I've gout about 3x speedup on my machine with this transformation.

It's quite rare in my experience that you can get to the point where
it makes sense to perform these low-level optimizations. You can
usually get decent performance by getting rid of all forks and
replacing loops with expansions. Array expansions are especially
powerful when it comes to making your scripts faster.

Roman.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-07-17  9:55 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-16  8:43 Nested function definition question Nick Cross
2019-07-16 14:13 ` Ray Andrews
2019-07-16 14:44   ` Nick Cross
2019-07-17  5:49     ` Roman Perepelitsa
2019-07-17  9:34       ` Nick Cross
2019-07-17  9:54         ` Roman Perepelitsa

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).