S
S
Shahelm2020-06-05 00:14:48
Asynchronous programming
Shahelm, 2020-06-05 00:14:48

Why are not all processor cores completely utilized?

The essence of the question is why all the processor cores are not completely utilized, one core is loaded at 100%, the rest periodically 0-30%. I assumed that tasks would be distributed evenly among all available threads (8 in my case) when starting tokio with runtime 'Threaded Scheduler' and starting tasks with tokio:spawn.

I'm running on: Intel(R) Core(TM) i7-3770 CPU

Briefly what happens in the code:
100,000 tasks are created (tokio::spawn), each task is a sql query to mysql that returns some rows, we count the total number of rows .

Dependencies:
mysql_async = "0.24.0-alpha"
dotenv = "0.15.0"
tokio = { version = "0.2.21", features = ["full"] }

use std::env;
use std::sync::Arc;

use mysql_async::{Pool, Error};
use mysql_async::prelude::*;

#[tokio::main]
async fn main() {
    dotenv::dotenv().ok();

    let pool = get_pool();
    let product_ids: Arc<Vec<u64>> = Arc::new(get_product_ids());

    let mut tasks = Vec::with_capacity(100002);

    let start = Instant::now();

    for _ in 1..=100000 {
        tasks.push(
            tokio::spawn(
                get_product(pool.clone(), product_ids.clone())
            )
        );
    }

    let mut number_of_products = 0;

    for result in tasks {
        number_of_products += result.await.unwrap().unwrap().len();
    }
}

fn get_pool() -> Pool {
    return mysql_async::Pool::new(env::var("DATABASE").expect("Failed to create connection pool");
}

async fn get_product(pool: Pool, product_ids: Arc<Vec<u64>>) -> Result<Vec<u64>, Error> {
    let mut connection = pool.get_conn().await.expect("Failed to get connection from pool");

    let query = format!(
        "SELECT product_id FROM products where product_id IN ({})",
        get_place_holders(product_ids.len())
    );

    connection
        .exec(query.as_str(), product_ids.as_ref())
        .await
}

fn get_place_holders(number_of_items: usize) -> String {
    vec!["?".to_string(); number_of_items].join(",")
}

fn get_product_ids() -> Vec<u64> {
    vec![123, 1234, 12345]
}

Some more information:
uname -a:
Linux ubuntu 4.10.0-38-generic #42~16.04.1-Ubuntu SMP Tue Oct 10 16:32:20 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

Build using the command:
cargo build --release

Additionally tried to increase options:
  • tokyo core_threads
  • mysql_async pool_max

Answer the question

In order to leave comments, you need to log in

3 answer(s)
S
Shahelm, 2020-06-05
@Shahelm

I figured it out, everything is trite, I did not correctly interpret the htop output, when it draws the process tree, it displays summary information on CPU consumption in the main process.
Thanks to all.

V
Vladimir Olohtonov, 2020-06-05
@sgjurano

Does the base itself work? And then you could very well run into it.

I
Ilya, 2020-06-05
@sarapinit

Most likely, the threads are waiting for the completion of IO operations (receiving data from the database over the network). I don't know Rust, but an underutilized CPU situation specific to asynchronous code.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question