- Notifications
You must be signed in to change notification settings - Fork1.3k
Improve: binaryops with number protocol#4139
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
6b4373a
tob8619f1
Compare This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
844a5b6
toee890ad
CompareUh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
@@ -237,8 +330,12 @@ impl PyNumber<'_> { | |||
obj.class().mro_find_map(|x| x.slots.as_number.load()) | |||
} | |||
pub fn methods(&self) -> &PyNumberMethods { | |||
self.methods | |||
pub fn methods<'a>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
pubfnmethods<'a>( | |
pubfnbinary_op<'a>( |
Uh oh!
There was an error while loading.Please reload this page.
let seq_a = PySequence::new(a, vm); | ||
let seq_b = PySequence::new(b, vm); | ||
// TODO: I think converting to isize process should be handled in repeat function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
who is "I"? the future reader will be confused.
If you think this topic requires discussion rather than leaving concrete TODO lists,
please consider opening an issue and leave here the issue number or link.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
If allowing arbitary n is not necessary for cpython compatibility, I thinkrepeat
is better to takeisize
orusize
because we can skip range check when we already know repeatingn
is possible.
If we are going to remove repetitive pattern, addingtry_repeat
with more inclusiven
will be possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
another idea is this will be a temporary code.
once all sequences implement number protocol correctly, they will handle it in their own number protocol.
a54c364
tob914c7f
Compareb914c7f
tofc55c89
Compareif let Some(slot_a) = slot_a { | ||
if let Some(slot_b) = slot_b { | ||
// Check if `a` is subclass of `b` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
According to CPython implementationhttps://github.com/python/cpython/blob/main/Objects/abstract.c#L842 , we may need to ensureb
is a "strict subclass" ofa
in order to useslot_b
for operation.
fast_isinstance
method seems including the situation thata
&b
belong to the same class,https://github.com/RustPython/RustPython/blob/main/vm/src/object/ext.rs#L459 .
Is there a method or proper approach to check "strict subclass" please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I don't think we have a function to do that.
But how about!a.is(b) && a.fast_issubclass(b)
?
when a and b are identical type,a.is(b)
will be true
&'a self, | ||
op_slot: &'a PyNumberMethodsOffset, | ||
vm: &VirtualMachine, | ||
) -> PyResult<&BinaryFunc> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
if we keep the namebinary_op
, the return type will be something other thanBinaryFunc
// Check if `a` is subclass of `b` | ||
if b.fast_isinstance(a.class()) { | ||
let ret = slot_b(num_a, b, self)?; | ||
if ret.rich_compare_bool( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@youknowone
Isrich_compare_bool
slow since it calls_cmp
which is not a trivial function?
Is it the suggested way to check whetherret
isself.ctx.not_implemented
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
How about usingret.fast_isinstance(PyNotImplemented::class(self))
to checkself.ctx.not_implemented
?
youknowoneMar 2, 2023 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
BecauseNotImplemented
is a singleton, I think this check can be fine:
ret.is(&self.ctx.not_implemented)
But not 100% sure because some type can override operators in weird way and rich_compare_bool will respect it. I have no idea about how CPython handle it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Oh, I missed the second comment. In this case,fast_isinstance
doesn't have any advantage to simpleis
calling. Becausefast_isinstance
doesn't check__isinstance__
python-implemented weird things will not be covered. But becauseNotImplemented
is always guaranteed to be singleton,fast_isinstance
doesn't check more thing. Sofast_isinstance
is not strong asrich_compare
but same weak as simpleis
.
merged through#4615 |
Uh oh!
There was an error while loading.Please reload this page.
Environments
rustpython
binary generated after usingcargo run --release
for faster runtime than debug one.Tasks
multiply
for testPyNumberBinaryOp
implementationor
=>type_::or_()
problemand
=>set
type doesn't have number protocolmod(remainder)
=>str
module - implant number protocol, compatible with bytes.rs's remainder methodProfiling
Benchmark source
Let me know if you have any good idea for improved benchmark!
flamegraph
Before

After

You can check the call-stackhas decreased comparing with before!
pyperf
This represents binaryops with number protocol can improve RustPython's performance just by applying only for multiplying operation.