Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UB free test for CString Drop #36607

Closed
wants to merge 1 commit into from
Closed

Conversation

matklad
Copy link
Member

@matklad matklad commented Sep 21, 2016

This implements an UB free (I hope :) ) test for #36264. Thanks to @petrochenkov and @nagisa for advice.

It also switched to volatile_write for zeroing per @Amanieu suggestion, which should prevent LLVM from optimizing our efforts away. @nagisa could you re-run your benchmark with this implementation to see if anything has changed?

@rust-highfive
Copy link
Collaborator

r? @alexcrichton

(rust_highfive has picked a reviewer for you, use r? to override)

@nagisa
Copy link
Member

nagisa commented Sep 21, 2016

@nagisa could you re-run your benchmark with this implementation to see if anything has changed?

The benchmark was in /tmp and I’ve restarted since.

@matklad
Copy link
Member Author

matklad commented Sep 21, 2016

volatile_write does make Drop a little slower according to my benchmark.

Source code: https://gist.github.com/matklad/87a77a7670b1b9144e09b9c4e62ea00f

Two runs without Drop for CString:

Baseline 1: empty String
ns per iter = 83
ns per iter = 83
ns per iter = 84

Baseline 2: hello world String
ns per iter = 161
ns per iter = 162
ns per iter = 161

Bench 1: empty CString
ns per iter = 103
ns per iter = 102
ns per iter = 101

Bench 2: hello world CString
ns per iter = 114
ns per iter = 115
ns per iter = 114
Baseline 1: empty String
ns per iter = 84
ns per iter = 83
ns per iter = 83

Baseline 2: hello world String
ns per iter = 161
ns per iter = 161
ns per iter = 162

Bench 1: empty CString
ns per iter = 100
ns per iter = 100
ns per iter = 100

Bench 2: hello world CString
ns per iter = 112
ns per iter = 111
ns per iter = 111

two runs with volatile write (this PR):

Baseline 1: empty String
ns per iter = 86
ns per iter = 86
ns per iter = 86

Baseline 2: hello world String
ns per iter = 162
ns per iter = 162
ns per iter = 162

Bench 1: empty CString
ns per iter = 113
ns per iter = 112
ns per iter = 112

Bench 2: hello world CString
ns per iter = 127
ns per iter = 127
ns per iter = 127
Baseline 1: empty String
ns per iter = 86
ns per iter = 85
ns per iter = 85

Baseline 2: hello world String
ns per iter = 166
ns per iter = 161
ns per iter = 161

Bench 1: empty CString
ns per iter = 115
ns per iter = 114
ns per iter = 114

Bench 2: hello world CString
ns per iter = 128
ns per iter = 129
ns per iter = 129

Will try to add a non volatile write bench later. Is there a faster way to build stdlib than make -j10 rustc-stage1 NO_REBUILD=1? And NO_REBUILD does not help here I guess?

@matklad
Copy link
Member Author

matklad commented Sep 22, 2016

Here's the one with non-volatile write (no perceivable difference with volatile):

Baseline 1: empty String
ns per iter = 86
ns per iter = 86
ns per iter = 86

Baseline 2: hello world String
ns per iter = 161
ns per iter = 161
ns per iter = 161

Bench 1: empty CString
ns per iter = 112
ns per iter = 112
ns per iter = 111

Bench 2: hello world CString
ns per iter = 126
ns per iter = 126
ns per iter = 126

@matklad
Copy link
Member Author

matklad commented Sep 22, 2016

Also it may make sense to compare these to the cost of the allocation, because the overhead kinda amortizes between new and drop. So, creating a hello world string is about 1000 ns on my machine.

@alexcrichton
Copy link
Member

I don't think it's worth using a volatile write to try to fix this test, it's just an opportunistic thing we do and if LLVM decides to remove it then that seems like a good thing. (it won't do so in debug mode, especially if we #[inline] this destructor).

If the test causes problems then I think it's safe to remove, it's probably not worth having a super elaborate test case for this.

@matklad
Copy link
Member Author

matklad commented Sep 25, 2016

The test works fine without volatile at the moment, though it could theoretically break in the future.

it won't do so in debug mode, especially if we #[inline] this destructor

Yes indeed. So I'll add #[inline(always)] and remove the test altogether tomorrow.

@matklad
Copy link
Member Author

matklad commented Sep 26, 2016

#36741

@matklad matklad closed this Sep 26, 2016
sophiajt pushed a commit to sophiajt/rust that referenced this pull request Sep 29, 2016
Remove CString drop test.

The test relies on the undefined behavior, and so may fail in some
circumstances. This can be worked around by stubbing a memory allocator
in the test, but it is a bit of work, and LLVM could still theoretically
eliminate the write of the zero byte in release mode (which is
intended).

So let's just remove the test and mark the function as inline. It
shouldn't be optimized away when inlined into the debug build of user's
code.

Supersedes rust-lang#36607

r? @alexcrichton
@matklad matklad deleted the ub-free-test branch July 9, 2019 12:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants