Comments (14)
I think I'm inclined to leave it how it is (including not doing #20, which would be contradictory to this proposal) for 0.1, and then based on use cases try to get more hard number for what further optimizations to perform.
from failure.
Obviously 1 word should be better than 2, I'd like benchmarks to know exactly how much better though.
Ideally I think we'd store the vtable or a pointer to it inline in the heap with the Error data, but I'm not sure how, on stable, to get a DST without automatically opting into a wide pointer representation.
from failure.
To be clearer:
- If we can store the vtable directly in the heap with the data on stable Rust, compatible back to
1.18.0
, I would accept that PR without any further argument. - I'd like some sense of the trade off (through benchmarks etc) to be convinced that we should double box this if we can't store the vtable in the heap.
from failure.
I grabbed some code from here and put a Result in it. Playground
- Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz
- rustc 1.23.0-nightly (e340996ff 2017-11-02)
For k=26 in release mode, a 1-word error takes 3.6 seconds and a 2-word error takes 5.0 seconds. The whole program is 40% slower.
from failure.
With Result<(), Error>
as the return types the difference is 80%, 2.3 seconds vs 4.2 seconds. Playground
from failure.
Can you expand on why the "man-or-boy test" is a good benchmark? I admit I don't fully understand the algorithm, but it doesn't seem like it imitates normal Rust code patterns to me.
Just intuitively (and handwavingly), there's some sort of curve when the Ok value is 1 or 0 words, where we reach a % of error cases at which it becomes more expensive to double allocate than the impact on the happy path is. Then there are, of course, cases where the Ok value is more than 2 words (like returning a vector for example), in which case it has no impact.
So to me the decision is a factor of the portion of code returning small success variants and the portion at which errors occur on average.
Not necessarily asking you to come up with some great, definite proof benchmark, just trying to talk through the trade offs.
from failure.
A different experiment I'd wonder about -- does it make a difference if the error has a destructor or not, keeping the size constant? Basically just testing Box<> vs *const T here.
from failure.
@bluss We have to have a destructor though, don't we? We don't want to leak the error data or the backtrace.
from failure.
I don't know this crate, sorry! 😄, I'm just curious if there are drawbacks to having such allocated data in errors or not. In my trial... looks like that benchmark speeds up slows down if one uses usize
instead of Box<String>
.
from failure.
You are right, that example is a worst case and not an average case.
In my heavily biased experience, I have always optimized for the happy path only. If some client were sending enough malformed requests to affect the server, they would be throttled. Even in the failure case, when deserialization fails there might be 10,000 Ok method calls before we arrive at the error and 10 Err method calls to propagate it to the caller. When serializing, practically every Ok value is 0 words -- in Formatter
and Serializer
. I guess that means I can't argue convincingly for which path to optimize. Would be interested to hear the opposite point of view where errors are frequent and Ok values are big.
from failure.
Your argument is pretty convincing. I think I'd like to hear other positions, so I'll leave this open, but right now I'm open to double boxing Error
.
from failure.
+1 for double-boxing from my perspective.
As a user of the library who is concerned about performance, optimizing for small Ok by double-boxing seems like the right tradeoff. I am generally less concerned about the double-deref performance impact once I have entered into an error state (and can work around this in the rare case it is a concern).
@withoutboats Failure
is a fantastic contribution to the community--thank you! Please let me know if I can help with any development in any way (beginner, with 1y of Rust experience)
And remember, all success begins with Failure! ;)
from failure.
It seems a thin pointer to dst would be ideal, but it's a bit too experimental now.
from failure.
It's not like we are going to expose a crate like thin
as public API, so I don't think it being experimental matters that much.
from failure.
Related Issues (20)
- Addition of name member to Fail trait is a semver-breaking change HOT 4
- Should `backtrace` dependency be optional? HOT 1
- Compat should override method source() HOT 1
- Repository field for `failure_derive` and `failure` do not match HOT 1
- Support for an alloc feature? HOT 1
- failure-v0.1.5 fails to compile with rustc-1.37.0 HOT 6
- Add option to derive Debug identical to Display HOT 1
- Collaborate on a "core::Error" crate with snafu, anyhow and other error crates HOT 1
- Update failure_derive dependencies HOT 1
- support `at` method using for locate error
- Move Repository To rust-lang HOT 7
- Fix guide example code
- Memory safe violation by abusing `__private_get_type_id__` HOT 1
- Propagate never type
- error: /lib64/libc.so.6: version `GLIBC_2.18' not found HOT 2
- 'backtrace' is forcing an increased MinSRV; pin 'backtrace' to `version = "<= 0.3.30"` HOT 6
- [FEATURE REQUEST] Add ability to `bail!` and `ensure!` error types.
- failure_derive won't build with quote 1.0.3 HOT 16
- Why does this exist? HOT 2
- "trailing semicolons in expression macro bodies" breaks with bail
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from failure.