Search code examples
performancerustpycharm

Why is my executable faster when ran from PyCharm?


I'm experiencing weird performance characteristics with this code depending on how I run it:

use std::time::Instant;

fn main() {
    let start_time = Instant::now();

    for p in 1..10000000 {
        if prime_check(p as f64) {
            println!("{} is prime", p);
        }
    }
    let end_time = Instant::now();
    let elapsed_time = end_time - start_time;
    println!("Elapsed time: {:?}", elapsed_time);
}

fn prime_check(p: f64) -> bool {
    let k: u64 = p.sqrt() as u64;
    for j in 2..=k {
        if p % j as f64 == 0.0 {
            return false;
        }
    }
    true
}

When I hit Alt+Shift+F10 in PyCharm with the Rust plugin, I get this:

9999943 is prime
9999971 is prime
9999973 is prime
9999991 is prime
Elapsed time: 11.537594s

When I build and run executable with rustc, I get this:

PS C:\Users\User\Desktop\Proj\Rs\src> rustc -O main.rs 
9999943 is prime
9999971 is prime
9999973 is prime
9999991 is prime
Elapsed time: 37.1560723s

I tried adding this to Cargo.toml but it made no difference:

[profile.dev]
opt-level = 3

How can I make rustc produced executable as fast as PyCharm? What causes such a difference?


Solution

  • For me, your code ran in:

    • cargo run: Elapsed time: 267.3377065s
    • cargo run --release: Elapsed time: 212.5371301s

    Now let's run it again without the printlns, because I suspect those are the main reason why your code is slow. And the fact that your code performs different in PowerShell and PyCharm is because their println handling is different.

    use std::time::Instant;
    
    fn main() {
        let start_time = Instant::now();
    
        let mut count: u64 = 0;
        for p in 1..10000000 {
            if prime_check(p as f64) {
                count += 1;
            }
        }
        
        let end_time = Instant::now();
        let elapsed_time = end_time - start_time;
        println!("Found {} primes.", count);
        println!("Elapsed time: {:?}", elapsed_time);
    }
    
    fn prime_check(p: f64) -> bool {
        let k: u64 = p.sqrt() as u64;
        for j in 2..=k {
            if p % j as f64 == 0.0 {
                return false;
            }
        }
        true
    }
    
    • cargo run:
      Found 664580 primes.
      Elapsed time: 54.3782759s
      
    • cargo run --release:
      Found 664580 primes.
      Elapsed time: 30.7077071s
      

    I suspect the output of this code will now perform similarly in PowerShell and PyCharm.


    As a further remark, I'd like to mention that your implementation of prime_check is dangerous - using f64 will introduce rounding errors at a certain point, and it will produce incorrect results.

    Use u64 instead:

    use std::time::Instant;
    
    fn main() {
        let start_time = Instant::now();
    
        let mut count: u64 = 0;
        for p in 1..10000000 {
            if prime_check(p) {
                count += 1;
            }
        }
    
        let end_time = Instant::now();
        let elapsed_time = end_time - start_time;
        println!("Found {} primes.", count);
        println!("Elapsed time: {:?}", elapsed_time);
    }
    
    fn prime_check(p: u64) -> bool {
        let k: u64 = (p as f64).sqrt() as u64;
        for j in 2..=k {
            if p % j == 0 {
                return false;
            }
        }
        true
    }
    
    Found 664580 primes.
    Elapsed time: 9.4109272s