lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: OMG - performance issue with Scheme engraver


From: David Kastrup
Subject: Re: OMG - performance issue with Scheme engraver
Date: Wed, 11 Jul 2018 11:55:47 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

Urs Liska <address@hidden> writes:

> Am 10.07.2018 um 19:48 schrieb Urs Liska:
>>
>> This seems to confirm that I should *not* break out of the for-each
>> loop that iterates over all-grobs in process-acknowledged.
>>
>> Does that mean that resetting the all-grobs list in
>> start-translation-timestep is the right approach#
>
> It's obviously not: while it reliably reduces processing time to what
> it should be it equally reliably misses all annotations except on the
> very first timestep.

Which is not the problem of resetting all-grobs in
start-translation-timestep but the asinine clearing of all-grobs inside
of the loop.

> What my engraver now does is:
>
>  * initialize all-grobs with #'()
>  * start-translation-timestep:
>    reset all-grobs to #'()
>  * acknowledgers:
>    prepend grob to all-grobs
>  * process-acknowledged
>    - iterate over all-grobs
>    - if an annotation is found, reset all-grobs to #'()
>
> The last behaviour is necessary because process-aknowledged is called
> multiple times and only in a later call the annotations are actually
> attached to the grobs

So because only in a later call the annotations are actually attached to
the grobs, you call out your list when seeing the first annotation?

Let's see how the current process_acknowledged framework does stuff:

void
Engraver_group::do_announces ()
{
  do
    {
      /*
        DOCME: why is this inside the loop?
       */
      for (SCM s = context ()->children_contexts ();
           scm_is_pair (s); s = scm_cdr (s))
        {
          Context *c = unsmob<Context> (scm_car (s));
          Engraver_group *group
            = dynamic_cast<Engraver_group *> (c->implementation ());
          if (group)
            group->do_announces ();
        }

      while (1)
        {
          precomputed_translator_foreach (PROCESS_ACKNOWLEDGED);
          if (announce_infos_.size () == 0)
            break;

          acknowledge_grobs ();
          announce_infos_.clear ();
        }
    }
  while (pending_grobs ());
}

pending_grobs () is true if there are any grobs in any subcontext's
announce_infos_ to be announced yet.

This is called once after calling everybody's process_music () from the
score-engraver.

So first it descends into all subcontexts at least once, doing all
announces and PROCESS_ACKNOWLEDGED calls at bottom level repeatedly
until every newly created grob in either process_acknowledgment or grob
acknowledger has seen a process_acknowledgment at bottom level.  Then
the next level acknowledges its collected grobs and, if any new grobs
have been created at any level in the course of its own
PROCESS_ACKNOWLEDGED/acknowledge cycle, it repeats.

Very wasteful.  Unfortunately, the Tweaks_engraver changes matters in
the Score-level acknowledger stage, with no PROCESS_ACKNOWLEDGED getting
called afterwards at lower levels unless there have been new grobs
produced at any level.

Very wasteful, all this.  If you are not going to actually create new
grobs (are you?), you can instead of process_acknowledged hook into
stop_translation_timestep which is called only once.

But it seems like you may be much better off just hooking into the Score
level process-acknowledged phase.  You are, after all, doing a global
kind of operation here.

-- 
David Kastrup



reply via email to

[Prev in Thread] Current Thread [Next in Thread]