Skip to content

Qc patches#902

Closed
filmor wants to merge 6 commits into
pythonnet:masterfrom
filmor:qc-patches
Closed

Qc patches#902
filmor wants to merge 6 commits into
pythonnet:masterfrom
filmor:qc-patches

Conversation

@filmor
Copy link
Copy Markdown
Member

@filmor filmor commented Jun 28, 2019

This is a rollup of 6 patches from the Quantconnect fork that can be easily applied on master. With this merged, the only things separating the fork from upstream will be

  1. The type conversion logic
  2. A few changes to the finalizer code
  3. The different versioning scheme

@AlexCatarino @Martin-Molinero @AlexCatarino, could you verify that I didn't botch your changes?

AlexCatarino and others added 6 commits June 28, 2019 07:48
- Adding `UnsafeDispose()` for `PyObject` which does not require
acquiring/releasing the lock
- Adding check before calling `SetArgsAndCause` for the `ClrObject`, the
call only makes sense when we are an exception and causes an overhead
- Adding new `interop` `type` cache holding a `bool`, true if its an `exception`.
- Adding a `setter` and `getter` cache for the `propertyobject`.
- Removing `ExceptionTypeCache` which was causing issues and fix for issue
caused performance overhead.
This addresses the following scenario:

1. A C# object `a` is created and filled with some data.
2. `a` is passed via Python.NET to Python. To do that Python.NET
   creates a wrapper object `w`, and stores reference to `a` in one of
   its fields.
3. Python code later passes `w` back to C#, e.g. calls `SomeCSharpMethod(w)`.
4. Python.NET has to unwrap `w`, so it reads the reference to `a` from it.

Prior to this change in 4. Python.NET had to determine what kind of an
object `a` is. If it is an exception, a different offset needed to be
used. That check was very expensive (up to 4 calls into Python
interpreter).

This change replaces that check with computing offset unconditionally
by subtracting a constant from the object size (which is read from the wrapper),
thus avoiding calls to Python interpreter.
Copy link
Copy Markdown
Member

@lostmsu lostmsu left a comment

Choose a reason for hiding this comment

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

@Martin-Molinero @filmor AlexCatarino who's gonna address the review comments?

if (info != null)
{
val += ArgPrecedence(info.ReturnType);
val += mi.DeclaringType == mi.ReflectedType ? 0 : 3000;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What does this 3000 mean? Can this be a named constant?


if (t.IsAssignableFrom(typeof(PyObject)))
{
return -1;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That makes TypeCode.Object entry in the switch below unreachable. Is it by design?
Also, negative precedence does not sound good. What is its purpose?

var methodInfo = propertyInfo.GetGetMethod();
if (methodInfo == null)
{
// if the getter is not public 'GetGetMethod' will not find it
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

According to MSDN, GetGetMethod has an overload, that returns non-public getters, so this condition can be removed, along with getterCacheFailed. Same for the setters I assume

Comment thread src/runtime/runtime.cs
return (t == tp) || PyType_IsSubtype(t, tp);
}

internal static bool PyObjectType_TypeCheck(IntPtr type, IntPtr tp)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For clarity, should rewrite the function above to use this function.

@lostmsu
Copy link
Copy Markdown
Member

lostmsu commented Jun 28, 2019

Also, some tests are failing apparently due to property access changes.

One test crashes during getter/setter delegate construction.

In two other cases the generated lambda converts incoming object into the type, that defined the property. For setters on value types that causes the object to be copied (via unboxing), and the original object is therefore left unmodified. Because nothing in .NET requires getters to be immutable, it might affect getters too (for example, if Lazy<T> would be struct, its getter would be unable to store the created instance).

@filmor
Copy link
Copy Markdown
Member Author

filmor commented Jun 28, 2019

The tests are probably also failing due to the missing conversion changes that I'd like to discuss separately.

@filmor
Copy link
Copy Markdown
Member Author

filmor commented Dec 10, 2020

I don't see this ever getting merged, so I'll close it.

@filmor filmor closed this Dec 10, 2020
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.

4 participants