once_cell is way faster

This commit is contained in:
Lev Kokotov
2022-02-10 17:05:20 -08:00
parent 0bec14ba1c
commit 06575eae7b
4 changed files with 31 additions and 18 deletions

2
Cargo.lock generated
View File

@@ -323,6 +323,8 @@ dependencies = [
"bytes",
"chrono",
"md-5",
"num_cpus",
"once_cell",
"rand",
"regex",
"serde",

View File

@@ -17,4 +17,6 @@ sha-1 = "0.10"
toml = "0.5"
serde = "1"
serde_derive = "1"
regex = "1"
regex = "1"
num_cpus = "1"
once_cell = "1"

View File

@@ -2,6 +2,7 @@
/// We are pretending to the server in this scenario,
/// and this module implements that.
use bytes::{Buf, BufMut, BytesMut};
use once_cell::sync::OnceCell;
use regex::Regex;
use tokio::io::{AsyncReadExt, BufReader};
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
@@ -14,8 +15,11 @@ use crate::pool::{ClientServerMap, ConnectionPool};
use crate::server::Server;
use crate::sharding::Sharder;
const SHARDING_REGEX: &str = r"SET SHARDING KEY TO '[0-9]+';";
const ROLE_REGEX: &str = r"SET SERVER ROLE TO '(PRIMARY|REPLICA)';";
pub const SHARDING_REGEX: &str = r"SET SHARDING KEY TO '[0-9]+';";
pub const ROLE_REGEX: &str = r"SET SERVER ROLE TO '(PRIMARY|REPLICA)';";
pub static SHARDING_REGEX_RE: OnceCell<Regex> = OnceCell::new();
pub static ROLE_REGEX_RE: OnceCell<Regex> = OnceCell::new();
/// The client state. One of these is created per client.
pub struct Client {
@@ -44,12 +48,6 @@ pub struct Client {
// Clients are mapped to servers while they use them. This allows a client
// to connect and cancel a query.
client_server_map: ClientServerMap,
// sharding regex
sharding_regex: Regex,
// role detection regex
role_regex: Regex,
}
impl Client {
@@ -61,9 +59,6 @@ impl Client {
client_server_map: ClientServerMap,
transaction_mode: bool,
) -> Result<Client, Error> {
let sharding_regex = Regex::new(SHARDING_REGEX).unwrap();
let role_regex = Regex::new(ROLE_REGEX).unwrap();
loop {
// Could be StartupMessage or SSLRequest
// which makes this variable length.
@@ -119,8 +114,6 @@ impl Client {
process_id: process_id,
secret_key: secret_key,
client_server_map: client_server_map,
sharding_regex: sharding_regex,
role_regex: role_regex,
});
}
@@ -140,8 +133,6 @@ impl Client {
process_id: process_id,
secret_key: secret_key,
client_server_map: client_server_map,
sharding_regex: sharding_regex,
role_regex: role_regex,
});
}
@@ -414,8 +405,12 @@ impl Client {
let len = buf.get_i32();
let query = String::from_utf8_lossy(&buf[..len as usize - 4 - 1]).to_ascii_uppercase(); // Don't read the ternminating null
let rgx = match SHARDING_REGEX_RE.get() {
Some(r) => r,
None => return None,
};
if self.sharding_regex.is_match(&query) {
if rgx.is_match(&query) {
let shard = query.split("'").collect::<Vec<&str>>()[1];
match shard.parse::<i64>() {
Ok(shard) => {
@@ -441,10 +436,14 @@ impl Client {
let len = buf.get_i32();
let query = String::from_utf8_lossy(&buf[..len as usize - 4 - 1]).to_ascii_uppercase();
let rgx = match ROLE_REGEX_RE.get() {
Some(r) => r,
None => return None,
};
// Copy / paste from above. If we get one more of these use cases,
// it'll be time to abstract :).
if self.role_regex.is_match(&query) {
if rgx.is_match(&query) {
let role = query.split("'").collect::<Vec<&str>>()[1];
match role {
"PRIMARY" => Some(Role::Primary),

View File

@@ -17,11 +17,14 @@ extern crate async_trait;
extern crate bb8;
extern crate bytes;
extern crate md5;
extern crate num_cpus;
extern crate once_cell;
extern crate serde;
extern crate serde_derive;
extern crate tokio;
extern crate toml;
use regex::Regex;
use tokio::net::TcpListener;
use std::collections::HashMap;
@@ -44,6 +47,13 @@ use pool::{ClientServerMap, ConnectionPool};
async fn main() {
println!("> Welcome to PgCat! Meow.");
client::SHARDING_REGEX_RE
.set(Regex::new(client::SHARDING_REGEX).unwrap())
.unwrap();
client::ROLE_REGEX_RE
.set(Regex::new(client::ROLE_REGEX).unwrap())
.unwrap();
let config = match config::parse("pgcat.toml").await {
Ok(config) => config,
Err(err) => {