Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upReduced performance when using question mark operator instead of `try!` #37939
Comments
This comment has been minimized.
This comment has been minimized.
|
I didn't read the implementation until now, I though they expanded to the exact same thing as try!() |
This comment has been minimized.
This comment has been minimized.
|
Might just need to stick a couple of |
This comment has been minimized.
This comment has been minimized.
StefanoD
commented
Nov 26, 2016
|
I'm curious why this issue doesn't even get a label like I-Slow. |
This comment has been minimized.
This comment has been minimized.
|
@sfackler I tried this ( |
dotdash
added
the
I-slow
label
Dec 8, 2016
This comment has been minimized.
This comment has been minimized.
|
I've found out why this is slow. Suppose you have an expression match Carrier::translate(res) {
Ok(val) => val,
Err(err) => return Carrier::from_error(From::from(err)),
}The real culprit is impl<U, V> Carrier for Result<U, V> {
type Success = U;
type Error = V;
fn from_success(u: U) -> Result<U, V> {
Ok(u)
}
fn from_error(e: V) -> Result<U, V> {
Err(e)
}
fn translate<T>(self) -> T
where T: Carrier<Success=U, Error=V>
{
match self {
Ok(u) => T::from_success(u),
Err(e) => T::from_error(e),
}
}
}In // Carrier::translate(<expr>)
let discr = {
// expand <expr>
let sub_expr = self.lower_expr(sub_expr);
let path = &["ops", "Carrier", "translate"];
let path = P(self.expr_std_path(unstable_span, path, ThinVec::new()));
P(self.expr_call(e.span, path, hir_vec![sub_expr]))
};Suppose we remove translation and implement the piece simply like this: // Carrier::translate(<expr>)
let discr = {
// expand <expr>
P(self.lower_expr(sub_expr))
};If we do that, there will be no slowdown in ratel-core due to question mark operators (I benchmarked it). I created a simple example that demonstrates the issue: https://is.gd/Q7PGzm identity:
.cfi_startproc
xorl %eax, %eax
cmpq $0, (%rsi)
movq 8(%rsi), %rcx
setne %al
movq %rax, (%rdi)
movq %rcx, 8(%rdi)
movq %rdi, %rax
retqYou can see there are unncesseary I'm a total beginner at rustc, so no idea how to proceed further. Should we perhaps detect identity functions within a MIR optimization pass? |
This comment has been minimized.
This comment has been minimized.
This was referenced Dec 12, 2016
scottlamb
added a commit
to scottlamb/moonfire-nvr
that referenced
this issue
Feb 27, 2017
frewsxcv
added a commit
to frewsxcv/rust
that referenced
this issue
Jun 1, 2017
frewsxcv
added a commit
to frewsxcv/rust
that referenced
this issue
Jun 1, 2017
frewsxcv
added a commit
to frewsxcv/rust
that referenced
this issue
Jun 1, 2017
yrashk
referenced this issue
Jul 4, 2017
Merged
Problem: instructions handling macros are obscure #321
BusyJay
referenced this issue
Jul 17, 2017
Merged
*: Add grpc interfaces used by transaction debugger #2012
Mark-Simulacrum
added
the
C-enhancement
label
Jul 26, 2017
This comment has been minimized.
This comment has been minimized.
kdy1
commented
Sep 28, 2017
•
|
I think this issue is fixed. Generated asm is same for try! and ?. https://play.rust-lang.org/?gist=625d88df305ace951a088e1cee2ec13a Edit: Typo |
This comment has been minimized.
This comment has been minimized.
StefanoD
commented
Sep 28, 2017
|
Even if this is fixed: Is there a unit test which prevents regression? |
This comment has been minimized.
This comment has been minimized.
|
We could have a Someone tag this as |
This comment has been minimized.
This comment has been minimized.
|
It looks like they both have the same bad code generation now, needs looking into. |
This comment has been minimized.
This comment has been minimized.
|
Example where it is compared with the identity function. Returning But it seems this example is not a good condensation of the issue, because I can't find any previous Rust version (in rust.godbolt) that has the desired identity function code gen even for the It doesn't show the difference between try and ?, but it shows something we can fix to improve them both. Edited: Update to another example code link (configurable Result type). |
This comment has been minimized.
This comment has been minimized.
|
I think https://reviews.llvm.org/D37216 should fix this, but it's a little stuck in the LLVM review queue. |
Mark-Simulacrum
added
the
E-needstest
label
Sep 29, 2017
matthewkmayer
referenced this issue
Jan 3, 2018
Merged
Ensure error responses from Ceph are parsed properly #892
This comment has been minimized.
This comment has been minimized.
|
@arielb1 it was reverted llvm-mirror/llvm@c87c1c0. |
This comment has been minimized.
This comment has been minimized.
|
I know that. It has a bug that I couldn't quite pin out. |
kennytm
removed
the
E-needstest
label
Feb 1, 2018
This comment has been minimized.
This comment has been minimized.
|
Still not fixed (tested nightly on playpen) |
kennytm
added
the
WG-codegen
label
Apr 24, 2018
This comment has been minimized.
This comment has been minimized.
|
This seems to be fixed (in stable). Tried the play link above. ; Function Attrs: noinline norecurse nounwind readnone uwtable
define { i64, i64 } @try_op(i64, i64) unnamed_addr #2 {
%3 = tail call { i64, i64 } @try_macro(i64 %0, i64 %1) #2
ret { i64, i64 } %3
}try_op:
jmp try_macro
try_macro:
xorl %eax, %eax
testq %rdi, %rdi
setne %al
movq %rsi, %rdx
retq |
kennytm
added
the
E-needstest
label
Aug 31, 2018
This comment has been minimized.
This comment has been minimized.
|
You can still provoke it to make a difference and introduce conditionals or more copies for the type T = (i32, i32);
type E = T;
type R = Result<T, E>;
#[no_mangle]
pub fn try_op(a: R) -> R {
Ok(a?)
}
#[no_mangle]
pub fn try_macro(a: R) -> R {
Ok(try!(a))
} |
nikic
added
the
A-LLVM
label
Dec 1, 2018
This comment has been minimized.
This comment has been minimized.
|
Looks like it regressed: https://godbolt.org/z/awKD_U |
birkenfeld commentedNov 22, 2016
•
edited
This was reported on the users forum , and I don't want it to get lost. Basically, replacing
try!by?resulted in ~20% performance loss in benchmarks:ratel-rust/ratel-core#48 (comment)
I've reproduced, but not further investigated, these findings. Is that expected right now? It's not a good argument for adopting the question mark :)