use ahash
this might actually be slower. do real benchmarks
This commit is contained in:
parent
3d4bfbfde0
commit
05af0551c9
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -5544,6 +5544,7 @@ dependencies = [
|
||||
name = "web3_proxy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ahash 0.8.0",
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
"argh",
|
||||
|
@ -34,14 +34,12 @@ where
|
||||
pub fn new(cache_size: u64, prefix: &str, rrl: RedisRateLimiter) -> Self {
|
||||
let ttl = rrl.period as u64;
|
||||
|
||||
let hasher = ahash::RandomState::new();
|
||||
|
||||
// TODO: think more about this ttl. if
|
||||
// TODO: time to live is not right. we want this ttl counter to start only after redis is down. this works for now
|
||||
let local_cache = Cache::builder()
|
||||
.time_to_live(Duration::from_secs(ttl))
|
||||
.max_capacity(cache_size)
|
||||
.name(prefix)
|
||||
.build_with_hasher(hasher);
|
||||
.build_with_hasher(ahash::RandomState::new());
|
||||
|
||||
Self {
|
||||
local_cache,
|
||||
|
@ -19,6 +19,7 @@ entities = { path = "../entities" }
|
||||
migration = { path = "../migration" }
|
||||
redis-rate-limiter = { path = "../redis-rate-limiter" }
|
||||
|
||||
ahash = "0.8.0"
|
||||
anyhow = { version = "1.0.65", features = ["backtrace"] }
|
||||
arc-swap = "1.5.1"
|
||||
argh = "0.1.8"
|
||||
|
@ -6,7 +6,7 @@ use crate::jsonrpc::JsonRpcForwardedResponse;
|
||||
use crate::jsonrpc::JsonRpcForwardedResponseEnum;
|
||||
use crate::jsonrpc::JsonRpcRequest;
|
||||
use crate::jsonrpc::JsonRpcRequestEnum;
|
||||
use crate::rpcs::blockchain::{ArcBlock, BlockHashesMap, BlockId};
|
||||
use crate::rpcs::blockchain::{ArcBlock, BlockId};
|
||||
use crate::rpcs::connections::Web3Connections;
|
||||
use crate::rpcs::request::OpenRequestHandleMetrics;
|
||||
use crate::rpcs::transactions::TxStatus;
|
||||
@ -54,7 +54,7 @@ static APP_USER_AGENT: &str = concat!(
|
||||
/// block hash, method, params
|
||||
// TODO: better name
|
||||
type ResponseCacheKey = (H256, String, Option<String>);
|
||||
type ResponseCache = Cache<ResponseCacheKey, JsonRpcForwardedResponse>;
|
||||
type ResponseCache = Cache<ResponseCacheKey, JsonRpcForwardedResponse, ahash::RandomState>;
|
||||
|
||||
pub type AnyhowJoinHandle<T> = JoinHandle<anyhow::Result<T>>;
|
||||
|
||||
@ -84,11 +84,11 @@ pub struct Web3ProxyApp {
|
||||
app_metrics: Arc<Web3ProxyAppMetrics>,
|
||||
open_request_handle_metrics: Arc<OpenRequestHandleMetrics>,
|
||||
/// store pending transactions that we've seen so that we don't send duplicates to subscribers
|
||||
pub pending_transactions: Cache<TxHash, TxStatus>,
|
||||
pub pending_transactions: Cache<TxHash, TxStatus, ahash::RandomState>,
|
||||
pub frontend_ip_rate_limiter: Option<DeferredRateLimiter<IpAddr>>,
|
||||
pub frontend_key_rate_limiter: Option<DeferredRateLimiter<Uuid>>,
|
||||
pub redis_pool: Option<RedisPool>,
|
||||
pub user_cache: Cache<Uuid, UserCacheValue>,
|
||||
pub user_cache: Cache<Uuid, UserCacheValue, ahash::RandomState>,
|
||||
}
|
||||
|
||||
/// flatten a JoinError into an anyhow error
|
||||
@ -232,7 +232,10 @@ impl Web3ProxyApp {
|
||||
|
||||
// test the pool
|
||||
if let Err(err) = redis_pool.get().await {
|
||||
error!("failed to connect to redis. some features will be disabled");
|
||||
error!(
|
||||
?err,
|
||||
"failed to connect to redis. some features will be disabled"
|
||||
);
|
||||
};
|
||||
|
||||
Some(redis_pool)
|
||||
@ -252,8 +255,9 @@ impl Web3ProxyApp {
|
||||
drop(pending_tx_receiver);
|
||||
|
||||
// TODO: sized and timed expiration!
|
||||
// TODO: put some in Redis, too?
|
||||
let pending_transactions = Cache::new(10000);
|
||||
let pending_transactions = Cache::builder()
|
||||
.max_capacity(10_000)
|
||||
.build_with_hasher(ahash::RandomState::new());
|
||||
|
||||
// TODO: don't drop the pending_tx_receiver. instead, read it to mark transactions as "seen". once seen, we won't re-send them
|
||||
// TODO: once a transaction is "Confirmed" we remove it from the map. this should prevent major memory leaks.
|
||||
@ -261,7 +265,9 @@ impl Web3ProxyApp {
|
||||
|
||||
// this block map is shared between balanced_rpcs and private_rpcs.
|
||||
// TODO: what limits should we have for expiration?
|
||||
let block_map = BlockHashesMap::new(10_000);
|
||||
let block_map = Cache::builder()
|
||||
.max_capacity(10_000)
|
||||
.build_with_hasher(ahash::RandomState::new());
|
||||
|
||||
let (balanced_rpcs, balanced_handle) = Web3Connections::spawn(
|
||||
top_config.app.chain_id,
|
||||
@ -332,9 +338,13 @@ impl Web3ProxyApp {
|
||||
}
|
||||
|
||||
// TODO: change this to a sized cache. theres some potentially giant responses that will break things
|
||||
let response_cache = Cache::new(10_000);
|
||||
let response_cache = Cache::builder()
|
||||
.max_capacity(10_000)
|
||||
.build_with_hasher(ahash::RandomState::new());
|
||||
|
||||
let user_cache = Cache::new(10_000);
|
||||
let user_cache = Cache::builder()
|
||||
.max_capacity(10_000)
|
||||
.build_with_hasher(ahash::RandomState::new());
|
||||
|
||||
let app = Self {
|
||||
config: top_config.app,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::rpcs::blockchain::BlockHashesMap;
|
||||
use crate::rpcs::blockchain::BlockHashesCache;
|
||||
use crate::rpcs::connection::Web3Connection;
|
||||
use crate::rpcs::request::OpenRequestHandleMetrics;
|
||||
use crate::{app::AnyhowJoinHandle, rpcs::blockchain::ArcBlock};
|
||||
@ -120,7 +120,7 @@ impl Web3ConnectionConfig {
|
||||
chain_id: u64,
|
||||
http_client: Option<reqwest::Client>,
|
||||
http_interval_sender: Option<Arc<broadcast::Sender<()>>>,
|
||||
block_map: BlockHashesMap,
|
||||
block_map: BlockHashesCache,
|
||||
block_sender: Option<flume::Sender<BlockAndRpc>>,
|
||||
tx_id_sender: Option<flume::Sender<TxHashAndRpc>>,
|
||||
open_request_handle_metrics: Arc<OpenRequestHandleMetrics>,
|
||||
|
@ -19,7 +19,7 @@ use tracing::{debug, trace, warn};
|
||||
// TODO: type for Hydrated Blocks with their full transactions?
|
||||
pub type ArcBlock = Arc<Block<TxHash>>;
|
||||
|
||||
pub type BlockHashesMap = Cache<H256, ArcBlock>;
|
||||
pub type BlockHashesCache = Cache<H256, ArcBlock, ahash::RandomState>;
|
||||
|
||||
/// A block's hash and number.
|
||||
#[derive(Clone, Debug, Default, From, Serialize)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
///! Rate-limited communication with a web3 provider.
|
||||
use super::blockchain::{ArcBlock, BlockHashesMap, BlockId};
|
||||
use super::blockchain::{ArcBlock, BlockHashesCache, BlockId};
|
||||
use super::provider::Web3Provider;
|
||||
use super::request::{OpenRequestHandle, OpenRequestHandleMetrics, OpenRequestResult};
|
||||
use crate::app::{flatten_handle, AnyhowJoinHandle};
|
||||
@ -69,7 +69,7 @@ impl Web3Connection {
|
||||
hard_limit: Option<(u64, RedisPool)>,
|
||||
// TODO: think more about this type
|
||||
soft_limit: u32,
|
||||
block_map: BlockHashesMap,
|
||||
block_map: BlockHashesCache,
|
||||
block_sender: Option<flume::Sender<BlockAndRpc>>,
|
||||
tx_id_sender: Option<flume::Sender<(TxHash, Arc<Self>)>>,
|
||||
reconnect: bool,
|
||||
@ -366,7 +366,7 @@ impl Web3Connection {
|
||||
self: &Arc<Self>,
|
||||
new_head_block: Result<Option<ArcBlock>, ProviderError>,
|
||||
block_sender: &flume::Sender<BlockAndRpc>,
|
||||
block_map: BlockHashesMap,
|
||||
block_map: BlockHashesCache,
|
||||
) -> anyhow::Result<()> {
|
||||
match new_head_block {
|
||||
Ok(None) => {
|
||||
@ -428,7 +428,7 @@ impl Web3Connection {
|
||||
async fn subscribe(
|
||||
self: Arc<Self>,
|
||||
http_interval_sender: Option<Arc<broadcast::Sender<()>>>,
|
||||
block_map: BlockHashesMap,
|
||||
block_map: BlockHashesCache,
|
||||
block_sender: Option<flume::Sender<BlockAndRpc>>,
|
||||
tx_id_sender: Option<flume::Sender<(TxHash, Arc<Self>)>>,
|
||||
reconnect: bool,
|
||||
@ -516,7 +516,7 @@ impl Web3Connection {
|
||||
self: Arc<Self>,
|
||||
http_interval_receiver: Option<broadcast::Receiver<()>>,
|
||||
block_sender: flume::Sender<BlockAndRpc>,
|
||||
block_map: BlockHashesMap,
|
||||
block_map: BlockHashesCache,
|
||||
) -> anyhow::Result<()> {
|
||||
info!(%self, "watching new heads");
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
///! Load balanced communication with a group of web3 providers
|
||||
use super::blockchain::{ArcBlock, BlockHashesMap};
|
||||
use super::blockchain::{ArcBlock, BlockHashesCache};
|
||||
use super::connection::Web3Connection;
|
||||
use super::request::{OpenRequestHandle, OpenRequestHandleMetrics, OpenRequestResult};
|
||||
use super::synced_connections::SyncedConnections;
|
||||
@ -36,12 +36,12 @@ pub struct Web3Connections {
|
||||
pub(super) conns: HashMap<String, Arc<Web3Connection>>,
|
||||
/// any requests will be forwarded to one (or more) of these connections
|
||||
pub(super) synced_connections: ArcSwap<SyncedConnections>,
|
||||
pub(super) pending_transactions: Cache<TxHash, TxStatus>,
|
||||
pub(super) pending_transactions: Cache<TxHash, TxStatus, ahash::RandomState>,
|
||||
/// TODO: this map is going to grow forever unless we do some sort of pruning. maybe store pruned in redis?
|
||||
/// all blocks, including orphans
|
||||
pub(super) block_hashes: BlockHashesMap,
|
||||
pub(super) block_hashes: BlockHashesCache,
|
||||
/// blocks on the heaviest chain
|
||||
pub(super) block_numbers: Cache<U64, H256>,
|
||||
pub(super) block_numbers: Cache<U64, H256, ahash::RandomState>,
|
||||
/// TODO: this map is going to grow forever unless we do some sort of pruning. maybe store pruned in redis?
|
||||
/// TODO: what should we use for edges?
|
||||
pub(super) blockchain_graphmap: AsyncRwLock<DiGraphMap<H256, u32>>,
|
||||
@ -57,12 +57,12 @@ impl Web3Connections {
|
||||
server_configs: HashMap<String, Web3ConnectionConfig>,
|
||||
http_client: Option<reqwest::Client>,
|
||||
redis_pool: Option<redis_rate_limiter::RedisPool>,
|
||||
block_map: BlockHashesMap,
|
||||
block_map: BlockHashesCache,
|
||||
head_block_sender: Option<watch::Sender<ArcBlock>>,
|
||||
min_sum_soft_limit: u32,
|
||||
min_synced_rpcs: usize,
|
||||
pending_tx_sender: Option<broadcast::Sender<TxStatus>>,
|
||||
pending_transactions: Cache<TxHash, TxStatus>,
|
||||
pending_transactions: Cache<TxHash, TxStatus, ahash::RandomState>,
|
||||
open_request_handle_metrics: Arc<OpenRequestHandleMetrics>,
|
||||
) -> anyhow::Result<(Arc<Self>, AnyhowJoinHandle<()>)> {
|
||||
let (pending_tx_id_sender, pending_tx_id_receiver) = flume::unbounded();
|
||||
@ -176,8 +176,14 @@ impl Web3Connections {
|
||||
let synced_connections = SyncedConnections::default();
|
||||
|
||||
// TODO: sizing and expiration on these caches!
|
||||
let block_hashes = Cache::new(10000);
|
||||
let block_numbers = Cache::new(10000);
|
||||
let block_hashes = Cache::builder()
|
||||
.time_to_idle(Duration::from_secs(600))
|
||||
.max_capacity(10_000)
|
||||
.build_with_hasher(ahash::RandomState::new());
|
||||
let block_numbers = Cache::builder()
|
||||
.time_to_idle(Duration::from_secs(600))
|
||||
.max_capacity(10_000)
|
||||
.build_with_hasher(ahash::RandomState::new());
|
||||
|
||||
let connections = Arc::new(Self {
|
||||
conns: connections,
|
||||
|
Loading…
Reference in New Issue
Block a user