Warum läuft Vec :: keep nach dem Update auf Rust 1.38.0 langsamer?

8

Nachdem ich Rust von 1.36.0 auf Version 1.38.0 aktualisiert hatte, stellte ich fest, dass mein Programm langsamer läuft - um etwa 50%.

Mit habe perfich festgestellt, dass die Hälfte der Programmzeit alloc::vec::Vec<T>::retainin der neuen Version verbracht wird. In der älteren Version wird diese Funktion nicht einmal angezeigt. Warum retainsollte 1.38.0 so viel länger dauern?

Der Anruf bei retainerfolgt wie folgt:

some_vec.retain(|&x| x < DEADLINE);

deadlineist eine Konstante u32und some_vecist eine Vec<u32>.

Ich habe das Programm ohne die retainAufrufe in beiden Versionen ausgeführt. In diesem Fall war 1,38,0 im Durchschnitt immer noch langsamer, jedoch nur um ~ 10% anstelle der zuvor beobachteten> 50%.

Um zusammenzufassen, was in den Tests passiert ist:

Version 1.36.0

  • mit retain: ~ 18sec
  • ohne retain: ~ 11sec

Version 1.38.0

  • mit retain: ~ 28sec
  • ohne retain: ~ 12sec

Für ein reproduzierbares Beispiel können Sie versuchen:

use std::time::Instant;

fn main() {
    let start = Instant::now();
    let mut my_vec: Vec<u32>;
    for _ in 0..100_000 {
        my_vec = (0..10_000).collect();
        my_vec.retain(|&x| x < 9000);
        my_vec.retain(|&x| x < 8000);
        my_vec.retain(|&x| x < 7000);
        my_vec.retain(|&x| x < 6000);
        my_vec.retain(|&x| x < 5000);
        my_vec.retain(|&x| (x < 5) & (x > 2));
    }
    let duration = start.elapsed();
    println!("Program took: {:?}", duration);
}

Mit cargo +1.36.0 run --releaseund dann cargo +1.38.0 run --release.

Für dieses kleine Beispiel habe ich:

$ cargo +1.36.0 run --release
Program took: 4.624297719s

$ cargo +1.38.0 run --release
Program took: 8.293383522s
Miguel
quelle
3
Ich glaube, dies sollte dem Rust lang-Team gemeldet werden .
Peter Hall
Vielen Dank, dass Sie Ihre Frage als Antwort auf Ihr Feedback verbessert haben. Du hast es wirklich umgedreht! Ich hoffe du bekommst eine Antwort.
Trentcl
2
Ich habe ein wenig gegraben: 1.37.0 ist schnell wie 1.36.0; Nacht ist langsam. Die generierte MIR von 1.37 und 1.38 sieht für mich gleich aus, wenn Sie die Kommentare und die relative Reihenfolge der Funktionen außer Acht lassen. Dies impliziert entweder: rustc hat die Anzahl / Reihenfolge / Art der LLVM-Durchläufe geändert, oder die von rustc verwendete Version von LLVM hat sich zwischen 1.37 geändert und 1,38, in welchem ​​Fall dies eine LLVM-Regression sowie eine Rustc-Regression ist. Ich weiß leider nicht, wie ich das sagen soll.
Trentcl
Hier ist der Fehlerbericht, den @ Miguel eingereicht hat
schädlich

Antworten:

2

Im Allgemeinen ist rust.godbolt.org nützlich, um die Qualität des generierten Codes zu überprüfen (aber vergessen Sie nicht, Optimierungsflags hinzuzufügen!).

In Ihrem Fall retainhat sich der für generierte Code deutlich verschlechtert: https://rust.godbolt.org/z/ZhVCDg

Sie sollten dies also Rust als Leistungsregression melden .

Kornel
quelle
1
Ich habe bereits gemeldet, dass es rostet, wie auch @Peter Hall vorgeschlagen hat.
Miguel
4
Für die Neugierigen: github.com/rust-lang/rust/issues/65970
mcarton