Add str(int) and repr(int) fast path using i64 conversion#7302
Add str(int) and repr(int) fast path using i64 conversion#7302youknowone merged 2 commits intoRustPython:mainfrom
Conversation
- Skip __str__ method resolution for exact PyInt in PyObject::str() - Use i64::to_string() for small integers, BigInt::to_string() for large ones - ~36% improvement in str(int) benchmarks
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review infoConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughIntroduces a fast-path for converting Python integers to decimal strings: exact small integers use an i64-based conversion, while large integers fall back to BigInt string conversion; also routes PyObject.str to use this fast-path for exact PyInt objects. Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
crates/vm/src/protocol/object.rs (1)
379-389: Fast path implementation looks correct, but duplicates logic fromint.rs.The use of
downcast_exact::<PyInt>correctly ensures this optimization only applies to exactintinstances, preserving correct behavior for subclasses that may override__str__.However, the conversion logic at lines 382-385 duplicates the implementation in
int.rsrepr_str. If the helper method suggested inint.rsis added, this can be simplified:♻️ Proposed refactor using shared helper
// Fast path for exact int: skip __str__ method resolution let obj = match obj.downcast_exact::<PyInt>(vm) { Ok(int) => { - let s = match int.as_bigint().to_i64() { - Some(i) => i.to_string(), - None => int.as_bigint().to_string(), - }; + let s = int.to_str_radix_10(); return Ok(vm.ctx.new_str(s)); } Err(obj) => obj, };This also removes the need for the
ToPrimitiveimport in this file if no other code uses it.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/vm/src/protocol/object.rs` around lines 379 - 389, Fast path duplicates int -> string conversion logic; replace the manual bigint-to-string code inside the downcast_exact::<PyInt> match with the shared helper introduced in int.rs (call the helper function exposed for int stringification, e.g., repr_str or the new PyInt helper) so the branch becomes: downcast_exact::<PyInt> => { let s = <use the int.rs helper>(int); return Ok(vm.ctx.new_str(s)); }, and remove the now-unnecessary ToPrimitive import if no other code uses it; ensure you reference downcast_exact::<PyInt>, as_bigint()/to_i64() usage sites when locating the code to change.crates/vm/src/builtins/int.rs (1)
605-610: Code duplication withobject.rs.This conversion logic (try
to_i64()then fall back toBigInt::to_string()) is duplicated incrates/vm/src/protocol/object.rslines 382-385. Per coding guidelines, when branches share common logic, consider extracting the differing value first, then calling the common logic once.Consider adding a helper method to
PyIntthat both call sites can use:♻️ Proposed refactor to eliminate duplication
Add a helper method in this file:
impl PyInt { + /// Returns the string representation, using i64 fast path when possible. + #[inline] + pub fn to_str_radix_10(&self) -> String { + match self.value.to_i64() { + Some(i) => i.to_string(), + None => self.value.to_string(), + } + } + pub const fn as_bigint(&self) -> &BigInt { &self.value }Then simplify
repr_str:impl Representable for PyInt { #[inline] fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> { - Ok(match zelf.value.to_i64() { - Some(i) => i.to_string(), - None => zelf.value.to_string(), - }) + Ok(zelf.to_str_radix_10()) } }And update
object.rsto use the same helper (see related comment there).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/vm/src/builtins/int.rs` around lines 605 - 610, The repr construction logic is duplicated; add a helper on PyInt (e.g., a method like to_repr_string or repr_fallback) that returns the String by trying self.to_i64() then falling back to BigInt::to_string(), then change repr_str (fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String>) to call that helper on zelf.value (or on PyInt) and update the duplicate site in object.rs to use the same helper so the common logic lives in one place.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@crates/vm/src/builtins/int.rs`:
- Around line 605-610: The repr construction logic is duplicated; add a helper
on PyInt (e.g., a method like to_repr_string or repr_fallback) that returns the
String by trying self.to_i64() then falling back to BigInt::to_string(), then
change repr_str (fn repr_str(zelf: &Py<Self>, _vm: &VirtualMachine) ->
PyResult<String>) to call that helper on zelf.value (or on PyInt) and update the
duplicate site in object.rs to use the same helper so the common logic lives in
one place.
In `@crates/vm/src/protocol/object.rs`:
- Around line 379-389: Fast path duplicates int -> string conversion logic;
replace the manual bigint-to-string code inside the downcast_exact::<PyInt>
match with the shared helper introduced in int.rs (call the helper function
exposed for int stringification, e.g., repr_str or the new PyInt helper) so the
branch becomes: downcast_exact::<PyInt> => { let s = <use the int.rs
helper>(int); return Ok(vm.ctx.new_str(s)); }, and remove the now-unnecessary
ToPrimitive import if no other code uses it; ensure you reference
downcast_exact::<PyInt>, as_bigint()/to_i64() usage sites when locating the code
to change.
…#7302) * Add str(int) and repr(int) fast path using i64 conversion - Skip __str__ method resolution for exact PyInt in PyObject::str() - Use i64::to_string() for small integers, BigInt::to_string() for large ones - ~36% improvement in str(int) benchmarks * Extract PyInt::to_str_radix_10() to deduplicate i64 fast path logic
Summary by CodeRabbit