-
Notifications
You must be signed in to change notification settings - Fork 520
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
Circular Buffer: added memory leak tests for overwrite
and read
#1652
Conversation
Hello. Thanks for opening a PR on Exercism. We are currently in a phase of our journey where we have paused community contributions to allow us to take a breather and redesign our community model. You can learn more in this blog post. As such, all issues and PRs in this repository are being automatically closed. That doesn't mean we're not interested in your ideas, or that if you're stuck on something we don't want to help. The best place to discuss things is with our community on the Exercism Community Forum. You can use this link&category=rust) to copy this into a new topic there. Note: If this PR has been pre-approved, please link back to this PR on the forum thread and a maintainer or staff member will reopen it. |
Hah. The tests fail on the example solution. On the one hand, I'm not sure if the The example solution should be improved, using
|
The trait bounds `Default + Clone` are semantically incorrect. A proper circular buffer needs to handle all kinds of elements. The reason these bounds are here is because it allows to avoid `unsafe` while enjoying the most efficient memory layout. However, there is another performance downside: The implementations of `Default` and `Clone` may be expensive (e.g. cause heap allocations.) As came up in this discussion, there are other weird side effects, for example for `Rc` which has a non-standard implementation of `Clone`: #1652 The approach I chose here get's rid of the trait bounds and wraps every element in an `Option`. In the worst case, this may lead to twice the memory consumption. (e.g. `Option<u64>` takes 16 bytes because of alignment) This approach is semantically correct, but not the most performant. The most performant solution would be to use `unsafe`. I'd like to avoid that in example solutions.
I created a PR to improve the example solution. But I don't think the tests should be added anymore. The exercise is present in the problem-specifications repository, which means new tests should be added there. |
The trait bounds `Default + Clone` are semantically incorrect. A proper circular buffer needs to handle all kinds of elements. The reason these bounds are here is because it allows to avoid `unsafe` while enjoying the most efficient memory layout. However, there is another performance downside: The implementations of `Default` and `Clone` may be expensive (e.g. cause heap allocations.) As came up in this discussion, there are other weird side effects, for example for `Rc` which has a non-standard implementation of `Clone`: #1652 The approach I chose here get's rid of the trait bounds and wraps every element in an `Option`. In the worst case, this may lead to twice the memory consumption. (e.g. `Option<u64>` takes 16 bytes because of alignment) This approach is semantically correct, but not the most performant. The most performant solution would be to use `unsafe`. I'd like to avoid that in example solutions.
The trait bounds `Default + Clone` are semantically incorrect. A proper circular buffer needs to handle all kinds of elements. The reason these bounds are here is because it allows to avoid `unsafe` while enjoying the most efficient memory layout. However, there is another performance downside: The implementations of `Default` and `Clone` may be expensive (e.g. cause heap allocations.) As came up in this discussion, there are other weird side effects, for example for `Rc` which has a non-standard implementation of `Clone`: #1652 The approach I chose here get's rid of the trait bounds and wraps every element in an `Option`. In the worst case, this may lead to twice the memory consumption. (e.g. `Option<u64>` takes 16 bytes because of alignment) This approach is semantically correct, but not the most performant. The most performant solution would be to use `unsafe`. I'd like to avoid that in example solutions.
The trait bounds `Default + Clone` are semantically incorrect. A proper circular buffer needs to handle all kinds of elements. The reason these bounds are here is because it allows to avoid `unsafe` while enjoying the most efficient memory layout. However, there is another performance downside: The implementations of `Default` and `Clone` may be expensive (e.g. cause heap allocations.) As came up in this discussion, there are other weird side effects, for example for `Rc` which has a non-standard implementation of `Clone`: #1652 The approach I chose here get's rid of the trait bounds and wraps every element in an `Option`. In the worst case, this may lead to twice the memory consumption. (e.g. `Option<u64>` takes 16 bytes because of alignment) This approach is semantically correct, but not the most performant. The most performant solution would be to use `unsafe`. I'd like to avoid that in example solutions.
The trait bounds `Default + Clone` are semantically incorrect. A proper circular buffer needs to handle all kinds of elements. The reason these bounds are here is because it allows to avoid `unsafe` while enjoying the most efficient memory layout. However, there is another performance downside: The implementations of `Default` and `Clone` may be expensive (e.g. cause heap allocations.) As came up in this discussion, there are other weird side effects, for example for `Rc` which has a non-standard implementation of `Clone`: #1652 The approach I chose here get's rid of the trait bounds and wraps every element in an `Option`. In the worst case, this may lead to twice the memory consumption. (e.g. `Option<u64>` takes 16 bytes because of alignment) This approach is semantically correct, but not the most performant. The most performant solution would be to use `unsafe`. I'd like to avoid that in example solutions.
The trait bounds `Default + Clone` are semantically incorrect. A proper circular buffer needs to handle all kinds of elements. The reason these bounds are here is because it allows to avoid `unsafe` while enjoying the most efficient memory layout. However, there is another performance downside: The implementations of `Default` and `Clone` may be expensive (e.g. cause heap allocations.) As came up in this discussion, there are other weird side effects, for example for `Rc` which has a non-standard implementation of `Clone`: #1652 The approach I chose here get's rid of the trait bounds and wraps every element in an `Option`. In the worst case, this may lead to twice the memory consumption. (e.g. `Option<u64>` takes 16 bytes because of alignment) This approach is semantically correct, but not the most performant. The most performant solution would be to use `unsafe`. I'd like to avoid that in example solutions.
The trait bounds `Default + Clone` are semantically incorrect. A proper circular buffer needs to handle all kinds of elements. The reason these bounds are here is because it allows to avoid `unsafe` while enjoying the most efficient memory layout. However, there is another performance downside: The implementations of `Default` and `Clone` may be expensive (e.g. cause heap allocations.) As came up in this discussion, there are other weird side effects, for example for `Rc` which has a non-standard implementation of `Clone`: #1652 The approach I chose here get's rid of the trait bounds and wraps every element in an `Option`. In the worst case, this may lead to twice the memory consumption. (e.g. `Option<u64>` takes 16 bytes because of alignment) This approach is semantically correct, but not the most performant. The most performant solution would be to use `unsafe`. I'd like to avoid that in example solutions.
The trait bounds `Default + Clone` are semantically incorrect. A proper circular buffer needs to handle all kinds of elements. The reason these bounds are here is because it allows to avoid `unsafe` while enjoying the most efficient memory layout. However, there is another performance downside: The implementations of `Default` and `Clone` may be expensive (e.g. cause heap allocations.) As came up in this discussion, there are other weird side effects, for example for `Rc` which has a non-standard implementation of `Clone`: #1652 The approach I chose here get's rid of the trait bounds and wraps every element in an `Option`. In the worst case, this may lead to twice the memory consumption. (e.g. `Option<u64>` takes 16 bytes because of alignment) This approach is semantically correct, but not the most performant. The most performant solution would be to use `unsafe`. I'd like to avoid that in example solutions.
The trait bounds `Default + Clone` are semantically incorrect. A proper circular buffer needs to handle all kinds of elements. The reason these bounds are here is because it allows to avoid `unsafe` while enjoying the most efficient memory layout. However, there is another performance downside: The implementations of `Default` and `Clone` may be expensive (e.g. cause heap allocations.) As came up in this discussion, there are other weird side effects, for example for `Rc` which has a non-standard implementation of `Clone`: #1652 The approach I chose here get's rid of the trait bounds and wraps every element in an `Option`. In the worst case, this may lead to twice the memory consumption. (e.g. `Option<u64>` takes 16 bytes because of alignment) This approach is semantically correct, but not the most performant. The most performant solution would be to use `unsafe`. I'd like to avoid that in example solutions.
The trait bounds `Default + Clone` are semantically incorrect. A proper circular buffer needs to handle all kinds of elements. The reason these bounds are here is because it allows to avoid `unsafe` while enjoying the most efficient memory layout. However, there is another performance downside: The implementations of `Default` and `Clone` may be expensive (e.g. cause heap allocations.) As came up in this discussion, there are other weird side effects, for example for `Rc` which has a non-standard implementation of `Clone`: #1652 The approach I chose here get's rid of the trait bounds and wraps every element in an `Option`. In the worst case, this may lead to twice the memory consumption. (e.g. `Option<u64>` takes 16 bytes because of alignment) This approach is semantically correct, but not the most performant. The most performant solution would be to use `unsafe`. I'd like to avoid that in example solutions.
When solving this with
unsafe
, my mentor pointed out that myoverwrite
method must've been leaking memory. He was correct! And I fixed this issue in my next iteration.A few days ago however, I remembered that there was a test for memory leaks on the
clear
method. The test in question usesRc
and its strong count to check if memory has been freed or not from the buffer.I decided to base a new couple of tests on the same technique, and well, indeed my earlier buffer fails the
overwrite
test.I've added these two to make sure the test suite helps students implement a leak-free Buffer :)