caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Modify macro and caml_initialize function
       [not found] <20101204110006.A6F91BC57@yquem.inria.fr>
@ 2010-12-05 16:02 ` CUOQ Pascal
  2010-12-05 16:13   ` [Caml-list] " Basile Starynkevitch
  0 siblings, 1 reply; 3+ messages in thread
From: CUOQ Pascal @ 2010-12-05 16:02 UTC (permalink / raw)
  To: caml-list, caml-list

ygrek wrote:

> BTW, while we are on this topic, why the following is not in upstream yet?
>
> http://eigenclass.org/R2/writings/optimizing-caml_modify
>
> Looks like a clear win-win without drawbacks (increased code size shouldn't be significant
> cause Modify is only used in a couple of places). What do you think?

This is very interesting. Thanks for pointing it out.

I think there would be a couple of alternatives to check out
before calling the patch final
(and even so, it may always remain an outside patch,
depending on interest from OCaml maintainers).

Contrary to what is implied in that post,
Array.make does not call the Modify macro:
it calls the caml_initialize function.
If you want to make Array.make faster, there is
a simple improvement: replace the idiom below:

for (i = 0; i < size; i++) caml_initialize(&Field(res, i), init);

by a call to a single function caml_initialize_block
that factors the computation of the condition:

(Is_block (val) && Is_young (val) && Is_in_heap (fp)).

A quick "grep -3 caml_initialize byterun/*.c" 
reveals 4 (out of 5) call sites that could benefit from
the caml_initialize_block function.

In fact, this makes me wonder if, in the case of Array.map,
Array.init and so on, a workable approach could not be to
compute a few values at a time (saving them in local roots)
and write them all at once, again factoring the tests

Is_in_heap (fp)

and

caml_gc_phase == Phase_mark

The first suggestion seems to me an uniform improvement
with no downside, and it stands a slim chance of going in
someday. The second one, no so much, but it would
definitely be fun to try to make work.

Pascal


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

* Re: [Caml-list] Modify macro and caml_initialize function
  2010-12-05 16:02 ` Modify macro and caml_initialize function CUOQ Pascal
@ 2010-12-05 16:13   ` Basile Starynkevitch
  2010-12-05 16:49     ` Benedikt Meurer
  0 siblings, 1 reply; 3+ messages in thread
From: Basile Starynkevitch @ 2010-12-05 16:13 UTC (permalink / raw)
  To: CUOQ Pascal; +Cc: caml-list

On Sun, 5 Dec 2010 17:02:37 +0100
"CUOQ Pascal" <Pascal.CUOQ@cea.fr> wrote:

> ygrek wrote:
> 
> > BTW, while we are on this topic, why the following is not in upstream yet?
> >
> > http://eigenclass.org/R2/writings/optimizing-caml_modify
> >
> > Looks like a clear win-win without drawbacks (increased code size shouldn't be significant
> > cause Modify is only used in a couple of places). What do you think?
> 
> This is very interesting. Thanks for pointing it out.


Sorry to be nitpicking, but...

IIRC, there might be some rare occasions where the Modify macro could
be called several times in a C routine. And then you've got several
caml_modify_maybe_add_to_ref_table labels in the same C routine.

With GCC, you could use a local __label__
http://gcc.gnu.org/onlinedocs/gcc/Local-Labels.html but if you want to
be portable to non GCC compilers, you'll need a Modify macro which
generates a unique label (perhaps using __LINE__ for that purpose).

I am thinking of something like [UNTESTED CODE]

#define Modify(fp, val) Modify_at(fp, val, __LINE__)

#define Modify_at(fp, val, lin) do{                                         \
  value in_heap = 0;                                                        \
  value _old_ = *(fp);                                                      \
  *(fp) = (val);                                                            \
  if (caml_gc_phase == Phase_mark) {                                        \
    if (Is_in_heap (fp)) {                                                  \
      caml_darken (_old_, NULL);                                            \
      in_heap = 1;                                                          \
      goto caml_modify_maybe_add_to_ref_table##Lin;                         \
    }                                                                       \
  } else {                                                                  \
      caml_modify_maybe_add_to_ref_table##Lin:                              \
      if (Is_block (val) && Is_young (val)                                  \
          && ! (Is_block (_old_) && Is_young (_old_)) &&                    \
          (in_heap || Is_in_heap (fp)) ){                                   \
        if (caml_ref_table.ptr >= caml_ref_table.limit){                    \
          CAMLassert (caml_ref_table.ptr == caml_ref_table.limit);          \
          caml_realloc_ref_table (&caml_ref_table);                         \
        }                                                                   \
        *caml_ref_table.ptr++ = (fp);                                       \
      }                                                                     \
  }                                                                         \
}while(0)

Cheers.
-- 
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mine, sont seulement les miennes} ***


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

* Re: [Caml-list] Modify macro and caml_initialize function
  2010-12-05 16:13   ` [Caml-list] " Basile Starynkevitch
@ 2010-12-05 16:49     ` Benedikt Meurer
  0 siblings, 0 replies; 3+ messages in thread
From: Benedikt Meurer @ 2010-12-05 16:49 UTC (permalink / raw)
  To: caml-list


On Dec 5, 2010, at 17:13 , Basile Starynkevitch wrote:

> On Sun, 5 Dec 2010 17:02:37 +0100
> "CUOQ Pascal" <Pascal.CUOQ@cea.fr> wrote:
> 
>> ygrek wrote:
>> 
>>> BTW, while we are on this topic, why the following is not in upstream yet?
>>> 
>>> http://eigenclass.org/R2/writings/optimizing-caml_modify
>>> 
>>> Looks like a clear win-win without drawbacks (increased code size shouldn't be significant
>>> cause Modify is only used in a couple of places). What do you think?
>> 
>> This is very interesting. Thanks for pointing it out.
> 
> 
> Sorry to be nitpicking, but...
> 
> IIRC, there might be some rare occasions where the Modify macro could
> be called several times in a C routine. And then you've got several
> caml_modify_maybe_add_to_ref_table labels in the same C routine.
> 
> With GCC, you could use a local __label__
> http://gcc.gnu.org/onlinedocs/gcc/Local-Labels.html but if you want to
> be portable to non GCC compilers, you'll need a Modify macro which
> generates a unique label (perhaps using __LINE__ for that purpose).
> 
> I am thinking of something like [UNTESTED CODE]
> 
> #define Modify(fp, val) Modify_at(fp, val, __LINE__)
> 
> #define Modify_at(fp, val, lin) do{                                         \
>  value in_heap = 0;                                                        \
>  value _old_ = *(fp);                                                      \
>  *(fp) = (val);                                                            \
>  if (caml_gc_phase == Phase_mark) {                                        \
>    if (Is_in_heap (fp)) {                                                  \
>      caml_darken (_old_, NULL);                                            \
>      in_heap = 1;                                                          \
>      goto caml_modify_maybe_add_to_ref_table##Lin;                         \
>    }                                                                       \
>  } else {                                                                  \
>      caml_modify_maybe_add_to_ref_table##Lin:                              \
>      if (Is_block (val) && Is_young (val)                                  \
>          && ! (Is_block (_old_) && Is_young (_old_)) &&                    \
>          (in_heap || Is_in_heap (fp)) ){                                   \
>        if (caml_ref_table.ptr >= caml_ref_table.limit){                    \
>          CAMLassert (caml_ref_table.ptr == caml_ref_table.limit);          \
>          caml_realloc_ref_table (&caml_ref_table);                         \
>        }                                                                   \
>        *caml_ref_table.ptr++ = (fp);                                       \
>      }                                                                     \
>  }                                                                         \
> }while(0)

Just use a static inline function, maybe with __attribute__((force_inline)) for GCC.

Benedikt

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

end of thread, other threads:[~2010-12-05 16:49 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20101204110006.A6F91BC57@yquem.inria.fr>
2010-12-05 16:02 ` Modify macro and caml_initialize function CUOQ Pascal
2010-12-05 16:13   ` [Caml-list] " Basile Starynkevitch
2010-12-05 16:49     ` Benedikt Meurer

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).