2016-04-28 22 views
5

Şu anda doing more stuff with arrays'u arıyorum, ancak bu işlevlerin performansı bir şekilde Leaked<T> dizininin önüne geçmesine izin verildiğinde daha iyi olabilir, sadece işlev bittiğinde onu açmak için. Bu, a) güvensizlik getirmeden ve b) catch_panic(_) ayarını yapmadan sızıntı amplifikasyonu kullanmamıza izin verecektir. Bu bir şekilde Rust'ta mümkün mü? bir yineleyici bir jenerik dizi (bu tabii ki çalışmaz) oluşturarak ÖrneğinBir değerin önünü açmak ve açmak için bir yol var mı?

:

#[inline] 
fn map_inner<I, S, F, T, N>(list: I, f: F) -> GenericArray<T, N> 
where I: IntoIterator<Item=S>, F: Fn(&S) -> T, N: ArrayLength<T> { 
    unsafe { 
     // pre-leak the whole array, it's uninitialized anyway 
     let mut res : GenericArray<Leaked<T>, N> = std::mem::uninitialized(); 
     let i = list.into_iter(); 
     for r in res.iter_mut() { 
      // this could panic anytime 
      std::ptr::write(r, Leaked::new(f(i.next().unwrap()))) 
     } 
     // transmuting un-leaks the array 
     std::mem::transmute::<GenericArray<Leaked<T>, N>, 
           GenericArray<T, N>>(res) 
    } 
} 

şunu belirtmek zorundayım ki biz ya T büyüklüğüne veya türüne derleme zamanı erişimi olsaydı o Borçlarını (örneğin, Leaked<T> gibi) borçlanmadan gizleyebilir, bu mükemmel şekilde yapılabilir.

+0

Beklediğiniz performansın iyileştirilmesi nasıldır? Len'i arttırma değil mi? – malbarbo

+0

Panikleri yakalayarak sızmayı önlemeye çalışırsam (şimdilik sadece beta/gece çalışıyor), bir Vec’e toplanmaktan yaklaşık% 45 daha fazla verim elde ediyorum. Ön sızıntı yaparak daha da iyi sonuçlar alabileceğimi düşünüyorum. – llogiq

cevap

3

nodrop kullanmak mümkündür, ancak sızıntı yapabilir.

fn map_inner<I, S, F, T, N>(list: I, f: F) -> GenericArray<T, N> 
where I: IntoIterator<Item=S>, F: Fn(&S) -> T, N: ArrayLength<T> { 
    unsafe { 
     // pre-leak the whole array, it's uninitialized anyway 
     let mut res : NoDrop<GenericArray<T, N>> = NoDrop::new(std::mem::uninitialized()); 
     let i = list.into_iter(); 
     for r in res.iter_mut() { 
      // this could panic anytime 
      std::ptr::write(r, f(i.next().unwrap())) 
     } 
     res.into_inner() 
    } 
} 

ilk öğe (a) sonra i tüketilir ve r yazılır olduğunu varsayalım, panik olur. i'dan kalan öğeler düşer, ancak a öğesi olmaz. Her ne kadar is not no'lu sızdıran bellek güvenli olmadığı düşünülse de, bu arzu edilmez.

Soru linkinde anlatılan yaklaşımın gitmenin yolu olduğunu düşünüyorum. Vec ve ArrayVec uygulamalarına benzer. Yazdığım dizi kitaplığında benzer bir yaklaşım kullanıyorum.

+0

Teşekkürler! Tam olarak aradığım şey bu. – llogiq

+1

@llogiq İlgilendiğinizde, bu tür bir yapının sızıntı yapmadığını belirten başka bir soruyu yanıtlamak için bazı kodlar yazdım. Bkz. Http://stackoverflow.com/questions/36925673/how-can-i-initialize-an-array-using-a-function – malbarbo

+0

Tekrar teşekkürler - bu, çoğu zaman geldiğim şeye eşittir. Benim kriterlerim de çok umut verici - düz dizi inşaatına çok yakın. – llogiq

İlgili konular