Size: a a a

Rust — русскоговорящее сообществo

2020 March 26

Э

Эрик in Rust — русскоговорящее сообществo
Вафель
tl;dr: .iter().join(",").as_str()
    fn join(&mut self, sep: &str) -> String
       where Self::Item: std::fmt::Display
   {
       match self.next() {
           None => String::new(),
           Some(first_elt) => {
               // estimate lower bound of capacity needed
               let (lower, _) = self.size_hint();
               let mut result = String::with_capacity(sep.len() * lower);
               write!(&mut result, "{}", first_elt).unwrap();
               for elt in self {
                   result.push_str(sep);
                   write!(&mut result, "{}", elt).unwrap();
               }
               result
           }
       }
   }
источник

Э

Эрик in Rust — русскоговорящее сообществo
У них for _ in _, а не for_each(), хотя работают с impl Iterator, а не slice::Iter. Такое себе. Да ещё и по нижней границе размер строки считают.
источник

Э

Эрик in Rust — русскоговорящее сообществo
И куча unwrap()'ов. Целых два.
источник

r

red75prime in Rust — русскоговорящее сообществo
for_each ничем не отличается от for _ in _
источник

Э

Эрик in Rust — русскоговорящее сообществo
Да ладно, вчера же только обсуждали.
источник

r

red75prime in Rust — русскоговорящее сообществo
не видел. И что выяснили?
источник

Э

Эрик in Rust — русскоговорящее сообществo
Или не вчера был разговор про эффективность .next() на всяких Chain итераторах?
источник

r

red75prime in Rust — русскоговорящее сообществo
А нашёл
источник

Э

Эрик in Rust — русскоговорящее сообществo
for _ in _ превращается в while let Some(_) = iter.next() {}, а for_each(|_| {}); оптимизирован для частных итераторов.
источник

r

red75prime in Rust — русскоговорящее сообществo
Дешугаринг for в for_each уже немного обсуждали https://www.reddit.com/r/rust/comments/eiwhkn/why_is_iterator_so_much_faster/fcu7o4b/
источник

Э

Эрик in Rust — русскоговорящее сообществo
Ну как бы, да. Я тоже статьи читал перед тем как понять, что не так и почему оно не так.
источник

Э

Эрик in Rust — русскоговорящее сообществo
Короче, @WaffleLapkin , юзай лучше мой только что написанный join для итератора. И либу тащить не придётся и более эффективный, и поменять что-то проще.
источник

В

Вафель in Rust — русскоговорящее сообществo
Эрик
Короче, @WaffleLapkin , юзай лучше мой только что написанный join для итератора. И либу тащить не придётся и более эффективный, и поменять что-то проще.
нет
источник

Э

Эрик in Rust — русскоговорящее сообществo
Переслано от Эрик
Ну а если хочешь поэффективнее, то что-то такое:

let size = {
 let (low, high) = iter.size_hint();
 let s = if let Some(size) = high {
   size
 } else {
   cmp::max(low,MEDIUM_ITERATOR_SIZE)
 };
 s * (UPPER_MEDIUM_STRING_SIZE + SPLITTER_SIZE)
};

let mut buffer = String::with_capacity(size);

iter.for_each(|s| {
 buffer.push_str(s.as_str);
});
источник

Э

Эрик in Rust — русскоговорящее сообществo
Там, правда, надо написать ещё buffer.push(splitter);, а то я забыл.
источник

Э

Эрик in Rust — русскоговорящее сообществo
Реаллокатора ответ.
источник

r

red75prime in Rust — русскоговорящее сообществo
За время одного branch misprediction можно скопировать около 300 байт
источник

Э

Эрик in Rust — русскоговорящее сообществo
red75prime
За время одного branch misprediction можно скопировать около 300 байт
Аллокация не просто байты копирует, она место в куче выделяет. misprediction потому такой дорогой, что инструкции в кеш не те подгружаются и надо ползти в L2/L3 или ещё хуже - кучу, чтобы инструкции достать.
источник

Э

Эрик in Rust — русскоговорящее сообществo
При этом аллокация даже дольше, потому что там не просто в кучу лезет, а сперва ищет место в куче.
источник

r

red75prime in Rust — русскоговорящее сообществo
Это я так. К тому, что оценка производительности по ассемблеру дело сложное
источник