Qc patches#902
Conversation
- 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.
lostmsu
left a comment
There was a problem hiding this comment.
@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; |
There was a problem hiding this comment.
What does this 3000 mean? Can this be a named constant?
|
|
||
| if (t.IsAssignableFrom(typeof(PyObject))) | ||
| { | ||
| return -1; |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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
| return (t == tp) || PyType_IsSubtype(t, tp); | ||
| } | ||
|
|
||
| internal static bool PyObjectType_TypeCheck(IntPtr type, IntPtr tp) |
There was a problem hiding this comment.
For clarity, should rewrite the function above to use this function.
|
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 |
|
The tests are probably also failing due to the missing conversion changes that I'd like to discuss separately. |
|
I don't see this ever getting merged, so I'll close it. |
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
@AlexCatarino @Martin-Molinero @AlexCatarino, could you verify that I didn't botch your changes?