lite-rpc/history/examples/bench_postgres_lowlevel.rs

134 lines
3.6 KiB
Rust

use bytes::Bytes;
use futures_util::pin_mut;
use log::info;
use solana_lite_rpc_history::postgres::postgres_config::PostgresSessionConfig;
use solana_lite_rpc_history::postgres::postgres_session::PostgresWriteSession;
use solana_sdk::blake3::Hash;
use solana_sdk::signature::Signature;
use std::sync::Arc;
use tokio::time::Instant;
use tokio_postgres::binary_copy::BinaryCopyInWriter;
use tokio_postgres::types::Type;
use tokio_postgres::CopyInSink;
pub async fn copy_in(client: &tokio_postgres::Client) -> anyhow::Result<()> {
let statement = r#"
COPY transactions_copyin(
signature, slot, err, cu_requested, prioritization_fees, cu_consumed, recent_blockhash, message
) FROM STDIN BINARY
"#;
// BinaryCopyInWriter
// https://github.com/sfackler/rust-postgres/blob/master/tokio-postgres/tests/test/binary_copy.rs
let sink: CopyInSink<Bytes> = client.copy_in(statement).await.unwrap();
let sig = Signature::new_unique().to_string();
let slot = 200_000_000_i64;
let err = None::<&str>;
let cu_requested = None::<i64>;
let prioritization_fees = None::<i64>;
let cu_consumed = None::<i64>;
let recent_blockhash = Hash::new(&[1u8; 32]).to_string();
let message = "";
let started = Instant::now();
let writer = BinaryCopyInWriter::new(
sink,
&[
Type::TEXT,
Type::INT8,
Type::TEXT,
Type::INT8,
Type::INT8,
Type::INT8,
Type::TEXT,
Type::TEXT,
],
);
pin_mut!(writer);
const COUNT: usize = 100000;
for i in 0..COUNT {
let slot_x = slot + i as i64;
writer
.as_mut()
.write(&[
&sig,
&slot_x,
&err,
&cu_requested,
&prioritization_fees,
&cu_consumed,
&recent_blockhash,
&message,
])
.await
.unwrap();
}
writer.finish().await.unwrap();
info!(
"wrote {} rows in {:.2}ms",
COUNT,
started.elapsed().as_secs_f64() * 1000.0
);
Ok(())
}
#[tokio::main]
pub async fn main() {
tracing_subscriber::fmt::init();
let pg_session_config = PostgresSessionConfig::new_for_tests();
let session = PostgresWriteSession::new(pg_session_config)
.await
.unwrap()
.get_write_session()
.await;
let ddl_statement = r#"
CREATE TEMP TABLE transactions_copyin
(
signature text NOT NULL,
slot bigint NOT NULL,
err text ,
cu_requested bigint,
prioritization_fees bigint,
cu_consumed bigint,
recent_blockhash text NOT NULL,
message text NOT NULL
)
"#;
session.execute(ddl_statement, &[]).await.unwrap();
let row_count_before = count_rows(session.client.clone()).await;
let started = Instant::now();
copy_in(session.client.as_ref()).await.unwrap();
info!(
"copyin write rows in {:.2}ms",
started.elapsed().as_secs_f64() * 1000.0
);
let row_count_after = count_rows(session.client.clone()).await;
info!("total: {}", row_count_after);
info!(
"inserted: {}",
row_count_after.saturating_sub(row_count_before)
);
}
async fn count_rows(client: Arc<tokio_postgres::Client>) -> i64 {
let row = client
.query_one("SELECT count(*) FROM transactions_copyin", &[])
.await
.unwrap();
row.get::<_, i64>(0)
}