use anyhow::Context; use sqlx::{migrate::MigrateDatabase, QueryBuilder, Sqlite}; use std::{fs::File, time::Instant}; mod graph; mod geng; use crate::geng::GengIterator; mod compute; use simplelog::*; #[tokio::main] async fn main() -> anyhow::Result<()> { dotenv::dotenv().ok(); CombinedLogger::init(vec![ TermLogger::new( LevelFilter::Info, Config::default(), TerminalMode::Mixed, ColorChoice::Auto, ), WriteLogger::new( LevelFilter::Debug, Config::default(), File::create("test.log").unwrap(), ), ]) .unwrap(); let vert_num = std::env::args() .nth(1) .context("You should provide number of vertices in argument")? .parse::()?; let database_url = std::env::var("DATABASE_URL").expect("Expected DATABASE_URL in env"); if !sqlx::Sqlite::database_exists(&database_url).await? { log::info!("Database file doesn't exist. Creating '{database_url}'."); sqlx::Sqlite::create_database(&database_url).await?; } let db = sqlx::SqlitePool::connect(&database_url).await?; sqlx::query( "CREATE TABLE IF NOT EXISTS graphs (\ g6 VARCHAR NOT NULL,\ size INT NOT NULL,\ ind_dom INT NOT NULL,\ forced_geod INT NOT NULL);", ) .execute(&db) .await?; let gi = GengIterator::new(vert_num); let start = Instant::now(); const BATCH_SIZE: usize = 5000; log::info!("Started computation for {vert_num} vertices"); let mut count = 0; loop { let graphs = gi.take(BATCH_SIZE); let batch = Instant::now(); let tasks: Vec<_> = graphs .map(|g| tokio::spawn(compute::dominating_numbers(g))) .collect(); let part = futures::future::join_all(tasks).await; let sz = part.len(); let mut query = QueryBuilder::::new( "INSERT INTO graphs (g6, size, ind_dom, forced_geod) ", ); query.push_values(part, |mut b, res| { match res { Ok((g6, size, ind_dom, fg)) => { // log::debug!( // "inserting {} {} {:?} {:?}", // g6, // size, // ind_dom, // fg // ); b.push_bind(g6) .push_bind(size as u32) .push_bind(ind_dom.unwrap_or(0)) .push_bind(fg.unwrap_or(0)); } Err(_) => log::error!("Unable to push into query"), }; }); let err = query.build().execute(&db).await; if let Err(e) = err { log::error!("{e}"); } count += sz; log::info!( "Counted {count} in {}s", batch.elapsed().as_nanos() as f64 / 1e9 ); if sz < BATCH_SIZE { break; } } let elapsed = start.elapsed(); let time = elapsed.as_nanos(); log::info!("Time elapsed: {}s", time as f64 / 1e9); Ok(()) }