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

Missing ArrayVec::resize #72

Open
ghost opened this issue Sep 29, 2017 · 10 comments
Open

Missing ArrayVec::resize #72

ghost opened this issue Sep 29, 2017 · 10 comments

Comments

@ghost
Copy link

ghost commented Sep 29, 2017

I'm missing the resize functionality (similar to the std::vec::Vec::resize):

fn resize(&mut self, new_len: usize, value: T)

I have to fill some items in a random order, so first the array have to be resized with some default values before indexing can start.
I could use plain arrays, but I'd like to use ArrayVec for it's "virtual dynamic" size.

Is there a function for this I've missed?

Edit:
This is my workaround:

(0..count).for_each(|_| self.attributes.push(Attribute::new()));

@bluss
Copy link
Owner

bluss commented Sep 29, 2017

Using extend or FromIterator would be idiomatic here too, so think the existing functionality is already quite good for the use case

@pftbest
Copy link

pftbest commented Oct 7, 2017

@bluss I tried using extend for this, but the code is not ergonomic either:

arrv.extend([0u8; 100].iter().map(|&x| x));

Also it might be a slow operation inserting bytes one by one instead of memset.

@bluss
Copy link
Owner

bluss commented Oct 7, 2017

Nothing blocks adding resize to arrayvec. Extend and FromIterator are the answer to the question of missed methods, though.

@bluss
Copy link
Owner

bluss commented Oct 7, 2017

Fwiw, this benchmark shows that the extend loop is pretty good but it's running into that "SetLenOnDrop problem", where the alias analysis is not good enough. It's not managing to merge the adjacent byte writes into bigger writes, because it's also writing to the array length field in the same loop.

Benchmark used:

extern crate arrayvec;
#[macro_use] extern crate bencher;

use arrayvec::ArrayVec;

use bencher::Bencher;

fn extend(b: &mut Bencher) {
    let mut v = ArrayVec::<[u8; 1 << 16]>::new();
    let cap = v.capacity();
    b.iter(|| {
        v.clear();
        v.extend((0..cap).map(|_| 1));
        v[0]
    });
    b.bytes = v.capacity() as u64;
}


benchmark_group!(benches, extend);
benchmark_main!(benches);

Which means that it's the kind of sad mutable no alias issue?

Inner loop is this:

60:   mov    BYTE PTR [rsp+rbx*1+0x10021],0x1
 17,16lea    edx,[rbx+0x10001]              
mov    DWORD PTR [rsp+0x10024],edx   
mov    BYTE PTR [rsp+rbx*1+0x10022],0x1
 15,09lea    edx,[rbx+0x10002]              
mov    DWORD PTR [rsp+0x10024],edx   
 11,32mov    BYTE PTR [rsp+rbx*1+0x10023],0x1
 16,62lea    edx,[rbx+0x10003]              
mov    DWORD PTR [rsp+0x10024],edx   
  7,37mov    BYTE PTR [rsp+rbx*1+0x10024],0x1
 13,84lea    edx,[rbx+0x10004]              
mov    DWORD PTR [rsp+0x10024],edx   
 18,60add    rbx,0x4                      
       │     ↑ jne    60                          

@pftbest
Copy link

pftbest commented Oct 7, 2017

Sorry for off-topic, but there is also one other method I miss, extend_from_slice. I know that there is a write method that does exactly that, but it's not available on no_std targets, so I had to copy-paste it in my codebase.

@bluss
Copy link
Owner

bluss commented Oct 8, 2017

Fwiw, -Zmutable-noalias does not help with that problem. Will post a PR to improve .extend()

@bluss
Copy link
Owner

bluss commented Oct 26, 2017

@pftbest Is it the interface of the method or the performance? #74 shows that the performance of extend seems good enough for the use case.

@pftbest
Copy link

pftbest commented Oct 26, 2017

@bluss, sorry I didn't test #74 yet. Yes, I was concerned about the performance because I'm working with a microcontroller target that is not very fast. I will come back when I'll have some measurements.

tbu- added a commit to tbu-/arrayvec that referenced this issue Nov 1, 2017
`ArrayVec::resize_default`
`ArrayVec::resize`
`ArrayVec::try_resize_default`
`ArrayVec::try_resize`

Fixes bluss#72.
@clarfonthey
Copy link
Contributor

Is this method still desired? If not, an alternative might be spare_capacity_mut like rust-lang/rust#75017.

@kekeimiku
Copy link

What is the current status?

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

No branches or pull requests

4 participants