0

I'm writing a program which executes a command on server using ssh and gets the output.

The part I don't understand is lower in the code.

If the function waits and then returns a string, it works as expected, but if work with TCP it starts performing very bad. I expect that using 100 threads on 100 hosts will perform 100 times faster, because will open 100 sockets simultaneously.

In the sleep version, changing poolThreads directly affects the time of execution. In the version with TCP streams, changing pool from 1 to 100 with 100 hosts only speeds it up from 90 to 67 because some hosts are offline.

I read the documentation, but cannot find anything to help me.

use clap::{App, Arg};
use rayon::prelude::*;
use rayon::ThreadPoolBuilder;
use ssh2::Session;
use std::fmt::Display;
use std::io::prelude::*;
use std::io::{BufReader, Read};
use std::net::{TcpStream, ToSocketAddrs};
use std::thread::sleep;
use std::time::Duration;

fn process_host<A>(hostname: A) -> Result<String, String>
where
    A: ToSocketAddrs + Display,
{
    sleep(Duration::from_secs(1));
    return Ok(hostname.to_string());
    // here is the problem
    // -----------------------------------------------------------
    let tcp = match TcpStream::connect(&hostname) {
        Ok(a) => a,
        Err(e) => {
            return Err(format!("{}:{}", hostname, e).to_string());
        }
    };
    let mut sess = match Session::new() {
        Ok(a) => a,
        Err(e) => {
            // todo logging
            return Err(format!("{}:{}", hostname, e).to_string());
        }
    };
    sess.set_tcp_stream(tcp);
    match sess.handshake() {
        Ok(a) => a,
        Err(e) => {
            return Err(format!("{}:{}", hostname, e).to_string());
        }
    };
    Ok(format!("{}", hostname))
}


fn main() {

    let hosts = vec!["aaaaa:22", "bbbbbbb:22"];
    let pool = ThreadPoolBuilder::new()
        .num_threads(10)
        .build()
        .expect("failed creating pool");
    pool.install(|| {
        hosts
            .par_iter()
            .map(|x| process_host(x))
            .for_each(|x| println!("{:?}", x))
    });
}
Vladimir
  • 294
  • 1
  • 3
  • 10
  • It's hard to answer your question because it doesn't include a [MRE]. There are many parts present in the code that don't seem required to reproduce the problem. It would make it easier for us to help you if you try to *minimally* reproduce your error on the [Rust Playground](https://play.rust-lang.org) if possible, otherwise in a brand new Cargo project, then [edit] your question to include the additional info. There are [Rust-specific MRE tips](//stackoverflow.com/tags/rust/info) you can use to reduce your original code for posting here. Thanks! – Shepmaster Jan 15 '20 at 18:46
  • FWIW, your error handling code can be greatly simplified: `let tcp = TcpStream::connect(&hostname).map_err(|e| format!("{}:{}", hostname, e))?;` Also, there's no need to `.to_string()` the result of `format!`, it's already a `String`. – Shepmaster Jan 15 '20 at 18:50
  • @Shepmaster rewrited to simplify code – Vladimir Jan 15 '20 at 18:53
  • @Shepmaster I just don't know, how to make mre for io specific code, because thread wait performs in different way, than I expected – Vladimir Jan 15 '20 at 18:55
  • You state *but if work with TCP it starts performing very bad*, can you be more explicit about what you mean? How is it performing? Why do you think it should be better? Are you running your code in release mode? – Shepmaster Jan 15 '20 at 18:59
  • Your current code uses undefined variables: `s`. – Shepmaster Jan 15 '20 at 19:00
  • @Shepmaster sorry, it was working. Fixed that – Vladimir Jan 15 '20 at 19:02
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/206022/discussion-between-vladimir-and-shepmaster). – Vladimir Jan 15 '20 at 19:02

1 Answers1

0

To debug a such a problem, you need to analysis, where your program wastes its time. There're to ways: profiling and analyzing of TCP connections.
I suggest you 2 way, cause it's much easier. Dump traffic with wireshark, filter it by port 22. After this, use conversations tab. Here you can sort connections by time, and can see, that program doesn't speedup because of no time limit for ssh connection.

Vladimir
  • 294
  • 1
  • 3
  • 10