From romain.francois at dbmail.com  Sat Jan  2 18:42:58 2010
From: romain.francois at dbmail.com (Romain Francois)
Date: Sat, 02 Jan 2010 18:42:58 +0100
Subject: [Rd] R-devel Digest, Vol 83, Issue 2
In-Reply-To: <4B3F7ACD.2050106@stats.uwo.ca>
References: <mailman.11.1262430004.8711.r-devel@r-project.org>
	<4B3F7625.1080806@gmail.com> <4B3F7ACD.2050106@stats.uwo.ca>
Message-ID: <4B3F85A2.2080003@dbmail.com>

On 01/02/2010 05:56 PM, Duncan Murdoch wrote:
>
> On 02/01/2010 11:36 AM, Laurent Gautier wrote:
>> [Disclaimer: what is below reflects my understanding from reading the
>> R source, others will correct where deemed necessary]
>>
>> On 1/2/10 12:00 PM, r-devel-request at r-project.org wrote:
>>> Hello,
>>>
>>> We are currently making lots of changes to Rcpp (see the open Rcpp
>>> mailing list if interested [1] in the details).
>>>
>>> We are now using [2] R_PreserveObject and R_ReleaseObject to manage
>>> garbage collection instead of the PROTECT/UNPROTECT dance. This seems to
>>> work well, but I was wondering if there was documentation about it.
>>
>> The most precise technical documentation is in memory.c
>> PROTECT is an alias for Rf_protect, itself an alias for
>> SEXP protect(SEXP s);
>> and uses a stack (R_PPStack) to store protected objects.
>>
>>> In particular, if we preserve the same SEXP twice (or more), should we
>>> implement some sort of reference counting ?
>>
>> This depends on the requirements for your system.
>>
>> For example, in rpy2 I added a reference counting layer(*) because I
>> wanted to allow several Python objects to share the same underlying R
>> object, but that's not currently(*) counting how many times an object
>> should be freed.
>> (*: imperfect, but currently doing a very decent job - details upon
>> request).
>>
>> That kind of feature could be provided by R's C-level API, since this
>> could be seen of general use as well as give an opportunity to improve
>> the performances of the R_PreservedObject/R_ReleaseObject duo whenever
>> a lot of objects are protected and/or external code is
>> protecting/releasing objects through a FIFO proxy.
>>
>>
>>> Reading the source (below, from memory.c) I think not, but some
>>> confirmation would help.
>>
>> I understand the code in memory.c like an object preserved twice needs
>> to be freed twice: R_PreciousList is just a (linked) list, and
>> "R_PreserveObject(object)" adds the object to the beginning of the
>> list while "R_ReleaseObject(object)" removes the first "object" found
>> from the list.
>>
>>
>>
>>> void R_PreserveObject(SEXP object)
>>> {
>>> R_PreciousList = CONS(object, R_PreciousList);
>>> }
>>>
>>> static SEXP RecursiveRelease(SEXP object, SEXP list)
>>> {
>>> if (!isNull(list)) {
>>> if (object == CAR(list))
>>> return CDR(list);
>>> else
>>> CDR(list) = RecursiveRelease(object, CDR(list));
>>> }
>>> return list;
>>> }
>>>
>>> void R_ReleaseObject(SEXP object)
>>> {
>>> R_PreciousList = RecursiveRelease(object, R_PreciousList);
>>> }
>>>
>>>
>>> I'd also be interested if there is some ideas on the relative efficiency
>>> of the preserve/release mechanism compared to PROTECT/UNPROTECT.
>>
>> PROTECT/UNPROTECT is trading granularity for speed. It is a stack with
>> only tow operations possible:
>> - push 1 object into the stack
>> - pull (unprotect) N last objects from the stack
>
> UNPROTECT_PTR is also possible, which does a linear search through the
> stack and unprotects something possibly deep within it. There is also
> REPROTECT which allows you to replace an entry within the stack.

Thanks; I've used those when I played with the parser's code (for 
highlight). It felt slightly harder to use than preserve/release since 
you have to maintain the protect index, etc ...

I think I'll go as you say below, just maintain my own precious list, 
the way Preserve/Release does it.

Romain

> I would guess that UNPROTECT_PTR is more efficient than RecursiveRelease
> because it doesn't use so much stack space when it needs to go deep into
> the stack to release, but it is possible the compiler recognizes the
> tail recursion and RecursiveRelease is implemented efficiently. In that
> case it could be more efficient than UNPROTECT_PTR, which has to move
> all the other entries down to fill the newly vacated space. Really the
> only reliable way to answer efficiency questions like this is to try
> both ways and see which works better in your application.
>
> Another possibility is to maintain your own list or environment of
> objects, and just protect/preserve the list as a whole.
>
> Duncan Murdoch

-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://tr.im/IW9B : C++ exceptions at the R level
|- http://tr.im/IlMh : CPP package: exposing C++ objects
`- http://tr.im/HlX9 : new package : bibtex



[Rd] R-devel Digest, Vol 83, Issue 2
Romain Francois