Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upAdd consuming cheap cast #142
Conversation
|
Other than the cheap |
|
I haven't looked at this in detail so don't understand it yet but I'm not really a fan of growing the size of the CFTypes |
|
Can't we just transmute between Ref types to avoid Drop? |
|
Or rather transmute the wrapper types? |
|
Or perhaps add a method on the wrapper type that returns the Ref type but doesn't drop()? Most wrapper types could implement this using transmute to avoid the drop. |
|
@jrmuizel I guess it would be possible to use What are your arguments against growing the structs by one bool? |
|
I have now pushed a commit that removes |
|
|
Yes, keeping them pointer sized is probably very desirable. Especially since it was so easy to achieve the same results without adding the bool. |
80ab652
to
1433fec
|
I like these changes. |
| sum += number.to_i64().unwrap() | ||
| } | ||
|
|
||
| assert!(sum == 15); | ||
|
|
||
| for elem in arr.iter() { | ||
| let number: CFNumber = TCFType::wrap_under_get_rule(mem::transmute(elem)); | ||
| let number: CFNumber = TCFType::wrap_under_get_rule(mem::transmute(elem.as_concrete_TypeRef())); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
faern
Jan 17, 2018
Author
Contributor
Ehm.. They are not, any longer. they were before when I actually changed the structs to contain a bool, then the transmute did not work because the types were of different size. I'll remove it! It's removed in the commit after anyway, but anyhow.
|
@bors-servo r+ |
|
|
|
Optimally this should be rebased when #135 is merged and updated, since that PR add's a type that does not make use of the macro here. |
|
@bors-servo r+ |
|
|
|
@bors-servo p=1 |
|
PR #84 also adds a type without making use of the |
Add consuming cheap cast
There are a lot of places where we increment and decrement the retain count when we would not have to. For example, a very common use-case with PropertyLists is to just directly cast them to their correct sub type and then throw the PropertyList away (because there is nothing you can do with the PropertyList instance directly.)
The reason we do this, I guess, is mostly because all `Drop` implementations force a retain count decrement. So we have to keep incrementing it to keep it correct. But if we add a flag to types that can be used to disable the decrement, then we can also get rid of the increment when we virtually just want to cast a pointer between two types.
This PR implements this by adding a boolean flag to all CF structs that is used by the `Drop` impl to determine if it should `CFRelease` the instance or not. Then this flag is modified in appropriate places where we cast to other types and consume ourselves.
I added some benchmarks locally. I did not want to commit them since benchmarking only works on nighty, and I did not feel like adding a feature flag for it etc. Anyhow, the following benchmarks:
```rust
#[bench]
fn bench_before(b: &mut Bencher) {
let string = CFString::from_static_string("Bar");
b.iter(|| unsafe {
string.clone()
.to_CFPropertyList()
.downcast::<_, CFString>()
.unwrap()
.disable_release();
})
}
#[bench]
fn bench_after(b: &mut Bencher) {
let string = CFString::from_static_string("Bar");
b.iter(|| unsafe {
string.clone()
.into_CFPropertyList()
.downcast_into::<_, CFString>()
.unwrap()
.disable_release();
})
}
```
Given the following results:
```
test propertylist::test::bench_after ... bench: 16 ns/iter (+/- 3)
test propertylist::test::bench_before ... bench: 73 ns/iter (+/- 14)
```
The final call to `disable_release()` in the benchmarks are to prevent the type coming out of the `unwrap()` from calling `CFRelease` on drop, and thus avoid measuring that. I want to try to measure only `{to,into}_CFPropertyList`, `downcast` and `downcast_into`. The `clone` is needed because the `into` version requires it and it would then not be fair to not have it on both.
I would say that speeding it up by a factor of ~4 can be well worth it? (Well, that 4 is of course no good measurement of anything, microbenchmarks etc. etc.. The benchmark mostly shows that a lot can be gained from avoiding some retain counting.)
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/core-foundation-rs/142)
<!-- Reviewable:end -->
|
|
faern commentedJan 14, 2018
•
edited
There are a lot of places where we increment and decrement the retain count when we would not have to. For example, a very common use-case with PropertyLists is to just directly cast them to their correct sub type and then throw the PropertyList away (because there is nothing you can do with the PropertyList instance directly.)
The reason we do this, I guess, is mostly because all
Dropimplementations force a retain count decrement. So we have to keep incrementing it to keep it correct. But if we add a flag to types that can be used to disable the decrement, then we can also get rid of the increment when we virtually just want to cast a pointer between two types.This PR implements this by adding a boolean flag to all CF structs that is used by the
Dropimpl to determine if it shouldCFReleasethe instance or not. Then this flag is modified in appropriate places where we cast to other types and consume ourselves.I added some benchmarks locally. I did not want to commit them since benchmarking only works on nighty, and I did not feel like adding a feature flag for it etc. Anyhow, the following benchmarks:
Given the following results:
The final call to
disable_release()in the benchmarks are to prevent the type coming out of theunwrap()from callingCFReleaseon drop, and thus avoid measuring that. I want to try to measure only{to,into}_CFPropertyList,downcastanddowncast_into. Thecloneis needed because theintoversion requires it and it would then not be fair to not have it on both.I would say that speeding it up by a factor of ~4 can be well worth it? (Well, that 4 is of course no good measurement of anything, microbenchmarks etc. etc.. The benchmark mostly shows that a lot can be gained from avoiding some retain counting.)
This change is