Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

classic Classic list List threaded Threaded
56 messages Options
123
Reply | Threaded
Open this post in threaded view
|

Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

Dev mailing list
LGTM


https://codereview.appspot.com/561390043/diff/563450046/lily/score-engraver.cc
File lily/score-engraver.cc (right):

https://codereview.appspot.com/561390043/diff/563450046/lily/score-engraver.cc#newcode200
lily/score-engraver.cc:200: // This double the heap. TODO: don't do this
if we get close to
s/double/doubles/

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

nine.fierce.ballads

https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
File lily/include/score-engraver.hh (right):

https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode33
lily/include/score-engraver.hh:33: GC_word last_gc_count_;
FYI: Because we're using C++11 now, you have the option of providing the
default value of this member right here.

  GC_word last_gc_count_ = -1;

If you did that, you wouldn't have to mention this member in any
constructors.  IMO it would be even better than usual in this case
because it would get rid of a preprocessor conditional in the cc file.

https://codereview.appspot.com/561390043/diff/557260051/lily/score-engraver.cc
File lily/score-engraver.cc (right):

https://codereview.appspot.com/561390043/diff/557260051/lily/score-engraver.cc#newcode174
lily/score-engraver.cc:174: #include <gc.h>
It would be better to move this to the top, or if there is a reason it
can't be moved to the top, to comment.  Includes in the middle of a file
can frustrate maintainers on occasion when someone uses a namespace or
defines file-scope things before them that conflict with what's in them.

https://codereview.appspot.com/561390043/diff/557260051/lily/score-engraver.cc#newcode199
lily/score-engraver.cc:199: if (reclaimed < 0.2) {
TODO (?) make this threshold configurable

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

jonas.hahnfeld
In reply to this post by Dev mailing list

https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
File lily/include/score-engraver.hh (right):

https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode26
lily/include/score-engraver.hh:26: #include <gc.h>
This effectively adds a dependency on libgc which you should search for
at configure - it is not necessarily installed in a default location.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

jonas.hahnfeld
In reply to this post by Dev mailing list

https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
File lily/include/score-engraver.hh (right):

https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode26
lily/include/score-engraver.hh:26: #include <gc.h>
On 2020/02/01 11:00:40, hahnjo wrote:
> This effectively adds a dependency on libgc which you should search
for at
> configure - it is not necessarily installed in a default location.

I'm confused - does this mean `gc/gc.h` or `libguile/gc.h`? I think the
latter only includes `gc/gc.h` transitively through `libguile/bdw-gc.h`
if BUILDING_LIBGUILE is defined, so this code needs the first.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

hanwenn
In reply to this post by Dev mailing list
On 2020/02/01 11:00:41, hahnjo wrote:
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
> File lily/include/score-engraver.hh (right):
>
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode26
> lily/include/score-engraver.hh:26: #include <gc.h>
> This effectively adds a dependency on libgc which you should search
for at
> configure - it is not necessarily installed in a default location.

I've added a TODO for now. One complication is that libgc doesn't come
with pkg-config.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

hanwenn
In reply to this post by Dev mailing list

https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
File lily/include/score-engraver.hh (right):

https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode33
lily/include/score-engraver.hh:33: GC_word last_gc_count_;
On 2020/02/01 10:55:50, Dan Eble wrote:
> FYI: Because we're using C++11 now, you have the option of providing
the default
> value of this member right here.
>
>   GC_word last_gc_count_ = -1;
>
> If you did that, you wouldn't have to mention this member in any
constructors.
> IMO it would be even better than usual in this case because it would
get rid of
> a preprocessor conditional in the cc file.

Done.

https://codereview.appspot.com/561390043/diff/557260051/lily/score-engraver.cc
File lily/score-engraver.cc (right):

https://codereview.appspot.com/561390043/diff/557260051/lily/score-engraver.cc#newcode174
lily/score-engraver.cc:174: #include <gc.h>
On 2020/02/01 10:55:50, Dan Eble wrote:
> It would be better to move this to the top, or if there is a reason it
can't be
> moved to the top, to comment.  Includes in the middle of a file can
frustrate
> maintainers on occasion when someone uses a namespace or defines
file-scope
> things before them that conflict with what's in them.

moved to lily-guile.{cc,hh}

https://codereview.appspot.com/561390043/diff/557260051/lily/score-engraver.cc#newcode199
lily/score-engraver.cc:199: if (reclaimed < 0.2) {
On 2020/02/01 10:55:50, Dan Eble wrote:
> TODO (?) make this threshold configurable

1) Before we make this fancy, I'd rather see GUILE 2.x working fully.
I've added a note on how to disable this as a comment for now.

2) if people want to configure this locally, they should just set
GC_MAX_HEAPSIZE to their amount of RAM available.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

David Kastrup
In reply to this post by Dev mailing list
On 2020/02/01 20:49:09, hanwenn wrote:
> On 2020/02/01 11:00:41, hahnjo wrote:
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
> > File lily/include/score-engraver.hh (right):
> >
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode26
> > lily/include/score-engraver.hh:26: #include <gc.h>
> > This effectively adds a dependency on libgc which you should search
for at
> > configure - it is not necessarily installed in a default location.
>
> I've added a TODO for now. One complication is that libgc doesn't come
with
> pkg-config.

It seems like a bad idea to change the bgc parameters behind Guile's
back.  Does Guile not have any GC hooks of its own that one could use
for increasing the heap size or its behavior with regard to requesting
memory?

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

hanwenn
In reply to this post by Dev mailing list
On 2020/02/01 20:59:06, dak wrote:
> On 2020/02/01 20:49:09, hanwenn wrote:
> > On 2020/02/01 11:00:41, hahnjo wrote:
> > >
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
> > > File lily/include/score-engraver.hh (right):
> > >
> > >
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode26
> > > lily/include/score-engraver.hh:26: #include <gc.h>
> > > This effectively adds a dependency on libgc which you should
search for at
> > > configure - it is not necessarily installed in a default location.
> >
> > I've added a TODO for now. One complication is that libgc doesn't
come with
> > pkg-config.
>
> It seems like a bad idea to change the bgc parameters behind Guile's
back.

Can you give a specific reason why?

>  Does
> Guile not have any GC hooks of its own that one could use for
increasing the
> heap size or its behavior with regard to requesting memory?

I guess you could allocate a large block of memory, and then deallocate
it again.

The whole idea of GUILE moving to libgc is that it gets out of the
business of trying
to do GC. Why would they insert themselves into that game again?


https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

David Kastrup
In reply to this post by Dev mailing list
On 2020/02/01 21:23:51, hanwenn wrote:
> On 2020/02/01 20:59:06, dak wrote:
> > On 2020/02/01 20:49:09, hanwenn wrote:
> > > On 2020/02/01 11:00:41, hahnjo wrote:
> > > >
> > >
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
> > > > File lily/include/score-engraver.hh (right):
> > > >
> > > >
> > >
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode26
> > > > lily/include/score-engraver.hh:26: #include <gc.h>
> > > > This effectively adds a dependency on libgc which you should
search for at
> > > > configure - it is not necessarily installed in a default
location.
> > >
> > > I've added a TODO for now. One complication is that libgc doesn't
come with
> > > pkg-config.
> >
> > It seems like a bad idea to change the bgc parameters behind Guile's
back.
>
> Can you give a specific reason why?
>
> >  Does
> > Guile not have any GC hooks of its own that one could use for
increasing the
> > heap size or its behavior with regard to requesting memory?
>
> I guess you could allocate a large block of memory, and then
deallocate it
> again.
>
> The whole idea of GUILE moving to libgc is that it gets out of the
business of
> trying
> to do GC. Why would they insert themselves into that game again?

From the Guile-2.2 manual:

 -- C Function: void * scm_malloc (size_t SIZE)
 -- C Function: void * scm_calloc (size_t SIZE)
 [...]

     These functions will (indirectly) call
     ‘scm_gc_register_allocation’.

 -- C Function: void scm_gc_register_allocation (size_t SIZE)
     Informs the garbage collector that SIZE bytes have been allocated,
     which the collector would otherwise not have known about.

     In general, Scheme will decide to collect garbage only after some
     amount of memory has been allocated.  Calling this function will
     make the Scheme garbage collector know about more allocation, and
     thus run more often (as appropriate).

     It is especially important to call this function when large
     unmanaged allocations, like images, may be freed by small Scheme
     allocations, like foreign objects.

So it would appear that Guile does have an interface for the notion of
getting in memory pressure, and we incidentally also call those hooks
when we are allocating smob structures.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

jonas.hahnfeld
In reply to this post by Dev mailing list
On 2020/02/01 20:49:09, hanwenn wrote:
> On 2020/02/01 11:00:41, hahnjo wrote:
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
> > File lily/include/score-engraver.hh (right):
> >
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode26
> > lily/include/score-engraver.hh:26: #include <gc.h>
> > This effectively adds a dependency on libgc which you should search
for at
> > configure - it is not necessarily installed in a default location.
>
> I've added a TODO for now. One complication is that libgc doesn't come
with
> pkg-config.

This is just not true:
 $ pkg-config --libs bdw-gc
-lgc

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

hanwenn
In reply to this post by Dev mailing list
On 2020/02/02 09:49:50, hahnjo wrote:
> On 2020/02/01 20:49:09, hanwenn wrote:
> > On 2020/02/01 11:00:41, hahnjo wrote:
> > >
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
> > > File lily/include/score-engraver.hh (right):
> > >
> > >
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode26
> > > lily/include/score-engraver.hh:26: #include <gc.h>
> > > This effectively adds a dependency on libgc which you should
search for at
> > > configure - it is not necessarily installed in a default location.
> >
> > I've added a TODO for now. One complication is that libgc doesn't
come with
> > pkg-config.
>
> This is just not true:
>  $ pkg-config --libs bdw-gc
> -lgc

Oops! my bad. I didn't pay close enough attention to the file list.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

hanwenn
In reply to this post by Dev mailing list
On 2020/02/01 21:59:14, dak wrote:
> On 2020/02/01 21:23:51, hanwenn wrote:
> > On 2020/02/01 20:59:06, dak wrote:
> > > On 2020/02/01 20:49:09, hanwenn wrote:
> > > > On 2020/02/01 11:00:41, hahnjo wrote:
> > > > >
> > > >
> > >
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
> > > > > File lily/include/score-engraver.hh (right):
> > > > >
> > > > >
> > > >
> > >
> >
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode26
> > > > > lily/include/score-engraver.hh:26: #include <gc.h>
> > > > > This effectively adds a dependency on libgc which you should
search for
> at
> > > > > configure - it is not necessarily installed in a default
location.
> > > >
> > > > I've added a TODO for now. One complication is that libgc
doesn't come
> with
> > > > pkg-config.
> > >
> > > It seems like a bad idea to change the bgc parameters behind
Guile's back.
> >
> > Can you give a specific reason why?
> >
> > >  Does
> > > Guile not have any GC hooks of its own that one could use for
increasing the
> > > heap size or its behavior with regard to requesting memory?
> >
> > I guess you could allocate a large block of memory, and then
deallocate it
> > again.
> >
> > The whole idea of GUILE moving to libgc is that it gets out of the
business of

> > trying
> > to do GC. Why would they insert themselves into that game again?
>
> From the Guile-2.2 manual:
>
>  -- C Function: void * scm_malloc (size_t SIZE)
>  -- C Function: void * scm_calloc (size_t SIZE)
>  [...]
>
>      These functions will (indirectly) call
>      ‘scm_gc_register_allocation’.
>
>  -- C Function: void scm_gc_register_allocation (size_t SIZE)
>      Informs the garbage collector that SIZE bytes have been
allocated,

>      which the collector would otherwise not have known about.
>
>      In general, Scheme will decide to collect garbage only after some
>      amount of memory has been allocated.  Calling this function will
>      make the Scheme garbage collector know about more allocation, and
>      thus run more often (as appropriate).
>
>      It is especially important to call this function when large
>      unmanaged allocations, like images, may be freed by small Scheme
>      allocations, like foreign objects.
>
> So it would appear that Guile does have an interface for the notion of
getting
> in memory pressure, and we incidentally also call those hooks when we
are
> allocating smob structures.

that is a hook, but it's not the one we need. What we want is a way to
make BDW/Guile expand the heap even if it thinks it's not necessary.
scm_register_allocation is meant to increase the GC frequency, but we
want the opposite.

We could do scm_gc_malloc + scm_gc_free, but

1) it's doing more work than we need

2) there is a risk that the GC library will treat our large allocations
especially (e.g returning to the O/S on GC_free)

I think asking libgc to expand the heap is the best way to ask for a
larger heap.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

hanwenn
In reply to this post by Dev mailing list
On 2020/02/01 11:00:41, hahnjo wrote:
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh
> File lily/include/score-engraver.hh (right):
>
>
https://codereview.appspot.com/561390043/diff/557260051/lily/include/score-engraver.hh#newcode26
> lily/include/score-engraver.hh:26: #include <gc.h>
> This effectively adds a dependency on libgc which you should search
for at
> configure - it is not necessarily installed in a default location.

added an autoconf stanza.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

jonas.hahnfeld
In reply to this post by Dev mailing list

https://codereview.appspot.com/561390043/diff/565600046/configure.ac
File configure.ac (right):

https://codereview.appspot.com/561390043/diff/565600046/configure.ac#newcode270
configure.ac:270: PKG_CHECK_MODULES(BDWGC, bdw-gc)
This should fail if not found, you're using it unconditionally

https://codereview.appspot.com/561390043/diff/565600046/lily/lily-guile.cc
File lily/lily-guile.cc (right):

https://codereview.appspot.com/561390043/diff/565600046/lily/lily-guile.cc#newcode30
lily/lily-guile.cc:30: // pkg-config or other type of autodiscovery
mechanism on Fedora.
Remove comment

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

hanwenn
In reply to this post by Dev mailing list

https://codereview.appspot.com/561390043/diff/565600046/configure.ac
File configure.ac (right):

https://codereview.appspot.com/561390043/diff/565600046/configure.ac#newcode270
configure.ac:270: PKG_CHECK_MODULES(BDWGC, bdw-gc)
On 2020/02/02 13:21:09, hahnjo wrote:
> This should fail if not found, you're using it unconditionally

Done.

https://codereview.appspot.com/561390043/diff/565600046/lily/lily-guile.cc
File lily/lily-guile.cc (right):

https://codereview.appspot.com/561390043/diff/565600046/lily/lily-guile.cc#newcode30
lily/lily-guile.cc:30: // pkg-config or other type of autodiscovery
mechanism on Fedora.
On 2020/02/02 13:21:09, hahnjo wrote:
> Remove comment

Done.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

jonas.hahnfeld
In reply to this post by Dev mailing list
On 2020/02/02 13:43:25, hanwenn wrote:
> jonas' comments

The uploaded diff has the wrong base, it's reverting quite some changes
from master.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

hanwenn
In reply to this post by Dev mailing list
On 2020/02/02 13:45:34, hahnjo wrote:
> On 2020/02/02 13:43:25, hanwenn wrote:
> > jonas' comments
>
> The uploaded diff has the wrong base, it's reverting quite some
changes from
> master.

I hate Rietveld.

Fixed.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

jonas.hahnfeld
In reply to this post by Dev mailing list
I just tried to reproduce the timings for commits already in master and
this patch. To be honest I don't see a clear picture yet.

Yes, this change seems to improve the time spent for garbage collection,
but the real time reported by "time" only decreases by a fraction (less
than 50% of the saved time for gc). Also I consistently measure
increased total and gc time when toggling the setting of the initial
heap size, ie the change in master actually makes it slower for me.

My conclusion would be that we need to measure larger scores, not
executions less than 10s. This may be the use case that most users care
about, but AFAICS it's actually pretty hard to get reliable data for
now.
I've tried to use the MSDM example from
https://lists.gnu.org/archive/html/lilypond-user/2016-11/msg00700.html
which runs for around ~40s on my system, but it crashes with Guile 2.2:
GUILE signaled an error for the expression beginning here
#                                                                      
                                             
 (define-music-function (parser location )()                            
                                             
Unbound variable: ol

Should we maybe prioritize correctness over performance for now?
Comparing performance with a fully working LilyPond should be much
easier.

https://codereview.appspot.com/561390043/

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

David Kastrup
[hidden email] writes:

> I just tried to reproduce the timings for commits already in master and
> this patch. To be honest I don't see a clear picture yet.
>
> Yes, this change seems to improve the time spent for garbage collection,
> but the real time reported by "time" only decreases by a fraction (less
> than 50% of the saved time for gc). Also I consistently measure
> increased total and gc time when toggling the setting of the initial
> heap size, ie the change in master actually makes it slower for me.
>
> My conclusion would be that we need to measure larger scores, not
> executions less than 10s. This may be the use case that most users care
> about, but AFAICS it's actually pretty hard to get reliable data for
> now.
> I've tried to use the MSDM example from
> https://lists.gnu.org/archive/html/lilypond-user/2016-11/msg00700.html
> which runs for around ~40s on my system, but it crashes with Guile 2.2:
> GUILE signaled an error for the expression beginning here
> #                                                                      
>                                              
>  (define-music-function (parser location )()                            
>                                              
> Unbound variable: ol

The preceding line is

col =

so this is likely a matter of passing the wrong part of the file into
Guile when encountering # .  The file contains two 3-byte UTF-8
sequences above which could be thought to throw off the interpretation
by 4 bytes.  But it actually is off by 6 bytes if it is running into the
preceding "ol", as if the special characters/bytes are not seen at all.

--
David Kastrup

Reply | Threaded
Open this post in threaded view
|

Re: Grow heap aggressively during music interpretation (issue 561390043 by hanwenn@gmail.com)

hanwenn
For testing, use

https://github.com/hanwen/lilypond/tree/guile22-experiment

in particular, you need

https://github.com/hanwen/lilypond/commit/b696550379831ecec1519be6d59cd8a3003e5329

for the UTF-8 parsing. I fixed this a week ago, but due to  the delays
in getting the preceding fix in ("cleanup embedded SCM parsing"), I
couldn't send that for review yet.

For me, juggling 15 different outstanding code reviews at the same
time is the bane of the current development process.

On Sun, Feb 2, 2020 at 9:51 PM David Kastrup <[hidden email]> wrote:

>
> [hidden email] writes:
>
> > I just tried to reproduce the timings for commits already in master and
> > this patch. To be honest I don't see a clear picture yet.
> >
> > Yes, this change seems to improve the time spent for garbage collection,
> > but the real time reported by "time" only decreases by a fraction (less
> > than 50% of the saved time for gc). Also I consistently measure
> > increased total and gc time when toggling the setting of the initial
> > heap size, ie the change in master actually makes it slower for me.
> >
> > My conclusion would be that we need to measure larger scores, not
> > executions less than 10s. This may be the use case that most users care
> > about, but AFAICS it's actually pretty hard to get reliable data for
> > now.
> > I've tried to use the MSDM example from
> > https://lists.gnu.org/archive/html/lilypond-user/2016-11/msg00700.html
> > which runs for around ~40s on my system, but it crashes with Guile 2.2:
> > GUILE signaled an error for the expression beginning here
> > #
> >
> >  (define-music-function (parser location )()
> >
> > Unbound variable: ol
>
> The preceding line is
>
> col =
>
> so this is likely a matter of passing the wrong part of the file into
> Guile when encountering # .  The file contains two 3-byte UTF-8
> sequences above which could be thought to throw off the interpretation
> by 4 bytes.  But it actually is off by 6 bytes if it is running into the
> preceding "ol", as if the special characters/bytes are not seen at all.
>
> --
> David Kastrup



--
Han-Wen Nienhuys - [hidden email] - http://www.xs4all.nl/~hanwen

123