Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always call r_to_py S3 method when converting objects from Python to R #299

Merged
merged 2 commits into from
Jun 28, 2018

Conversation

jjallaire
Copy link
Member

Addresses #298

@kevinushey Could you review this please?

I'm wondering if the static references I introduced to the R reticulate environment and r_to_py() functions could cause any problems? (e.g. being feed at the end of a process lifetime when R is already gone?).

The other issue is ensuring that we have all of the memory semantics right (i.e. we won't either leak objects or leave an object without a reference causing a crash). This is about the lowest level change we could make in reticulate so has the potential to wreak havoc if it's not done correctly!

@kevinushey
Copy link
Collaborator

Given that reticulate has already picked up some reverse dependencies I could try running a revdepcheck to see if this PR breaks anything downstream.

I think that having static references to these Rcpp objects may be dangerous -- the destructor will attempt to unprotect the associated SEXP, which may no longer exist at shutdown time. I think leaving them as non-static would be okay.

@jjallaire
Copy link
Member Author

Okay, I got rid of the static.

I ran the tests against keras and tensorflow and both had no issues.

I think it would be good to also do some diagnostics along these lines:

  1. Run tests with GC_TORTURE
  2. Run tests with whatever CRAN uses for memory error checking

@jjallaire
Copy link
Member Author

Beyond that. I believe that I've gotten the memory semantics right here but it's definitely worth another pair of eyes tracking back the implications of things.

Would also be good to just empirically confirm that we aren't leaking any memory with the new implementation.

@kevinushey
Copy link
Collaborator

kevinushey commented Jun 27, 2018

If there were a memory leak, I would expect code like this to cause the R session's memory usage to blow up:

library(reticulate)
df <- data.frame(alpha = 1:1E3)
py_run_string('def identity(x): return x')
main <- import_main()
repeat main$identity(df)

All seems well in this case -- memory usage remains stable.

@jjallaire
Copy link
Member Author

Okay, I'm running right now with gctorture() set to the most stringent level to check that angle.


// call the R version and hold the return value in a PyObjectRef (SEXP wrapper)
// this object will be released when the function returns
PyObjectRef ref(r_to_py_fn(x, convert));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to make sure I understand the semantics, PyObjectRef itself is an R environment containing the associated Python wrapper object. A C finalizer is set on the Python object when this object is constructed, and that C finalizer will call Py_DecRef() when the parent R environment is cleaned up. To ensure that the object then lives beyond that cleanup, we need to explicitly increase the reference count (as is done below).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's exactly correct (note that py_to_r_cpp effectively does the same thing, incrementing the reference count before returning any Python object).

R CMD check with gctorture() is still running, no problems yet....

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, gctorture() succeeded. If you are good with the code changes I'll merge....

@kevinushey
Copy link
Collaborator

kevinushey commented Jun 28, 2018

LGTM! I think we're ready to merge.

I also ran a revdepcheck and all the downstream dependencies look good -- no breakages due to this change.

@jjallaire jjallaire merged commit a552f4a into master Jun 28, 2018
@ijlyttle
Copy link

ijlyttle commented Jul 8, 2018

Just a wee comment to say thanks for this: things get a little easier in altair.

We can now remove the r_to_py() call in the chart constructor:

alt$Chart(r_to_py(vega_data$cars()))

I was getting ready to file an issue, but no need!

cc @AliciaSchep

@t-kalinowski t-kalinowski deleted the bugfix/r-to-py-dispatch branch August 25, 2023 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants