Add PerfSamples column to blockstore (#12377)
* Add blockstore column to store performance sampling data * Add PerfSamples to purge/compaction
This commit is contained in:
@ -124,6 +124,7 @@ pub struct Blockstore {
|
|||||||
active_transaction_status_index: RwLock<u64>,
|
active_transaction_status_index: RwLock<u64>,
|
||||||
rewards_cf: LedgerColumn<cf::Rewards>,
|
rewards_cf: LedgerColumn<cf::Rewards>,
|
||||||
_blocktime_cf: LedgerColumn<cf::Blocktime>,
|
_blocktime_cf: LedgerColumn<cf::Blocktime>,
|
||||||
|
perf_samples_cf: LedgerColumn<cf::PerfSamples>,
|
||||||
last_root: Arc<RwLock<Slot>>,
|
last_root: Arc<RwLock<Slot>>,
|
||||||
insert_shreds_lock: Arc<Mutex<()>>,
|
insert_shreds_lock: Arc<Mutex<()>>,
|
||||||
pub new_shreds_signals: Vec<SyncSender<bool>>,
|
pub new_shreds_signals: Vec<SyncSender<bool>>,
|
||||||
@ -282,6 +283,7 @@ impl Blockstore {
|
|||||||
// This column is created (but never populated) in order to maintain compatibility with
|
// This column is created (but never populated) in order to maintain compatibility with
|
||||||
// newer versions of Blockstore.
|
// newer versions of Blockstore.
|
||||||
let _blocktime_cf = db.column();
|
let _blocktime_cf = db.column();
|
||||||
|
let perf_samples_cf = db.column();
|
||||||
|
|
||||||
let db = Arc::new(db);
|
let db = Arc::new(db);
|
||||||
|
|
||||||
@ -327,6 +329,7 @@ impl Blockstore {
|
|||||||
active_transaction_status_index: RwLock::new(active_transaction_status_index),
|
active_transaction_status_index: RwLock::new(active_transaction_status_index),
|
||||||
rewards_cf,
|
rewards_cf,
|
||||||
_blocktime_cf,
|
_blocktime_cf,
|
||||||
|
perf_samples_cf,
|
||||||
new_shreds_signals: vec![],
|
new_shreds_signals: vec![],
|
||||||
completed_slots_senders: vec![],
|
completed_slots_senders: vec![],
|
||||||
insert_shreds_lock: Arc::new(Mutex::new(())),
|
insert_shreds_lock: Arc::new(Mutex::new(())),
|
||||||
@ -2281,6 +2284,22 @@ impl Blockstore {
|
|||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_recent_perf_samples(&self, num: usize) -> Result<Vec<(Slot, PerfSample)>> {
|
||||||
|
Ok(self
|
||||||
|
.db
|
||||||
|
.iter::<cf::PerfSamples>(IteratorMode::End)?
|
||||||
|
.take(num)
|
||||||
|
.map(|(slot, data)| {
|
||||||
|
let perf_sample = deserialize(&data).unwrap();
|
||||||
|
(slot, perf_sample)
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_perf_sample(&self, index: Slot, perf_sample: &PerfSample) -> Result<()> {
|
||||||
|
self.perf_samples_cf.put(index, perf_sample)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the entry vector for the slot starting with `shred_start_index`
|
/// Returns the entry vector for the slot starting with `shred_start_index`
|
||||||
pub fn get_slot_entries(&self, slot: Slot, shred_start_index: u64) -> Result<Vec<Entry>> {
|
pub fn get_slot_entries(&self, slot: Slot, shred_start_index: u64) -> Result<Vec<Entry>> {
|
||||||
self.get_slot_entries_with_shred_info(slot, shred_start_index, false)
|
self.get_slot_entries_with_shred_info(slot, shred_start_index, false)
|
||||||
@ -6716,6 +6735,38 @@ pub mod tests {
|
|||||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_write_get_perf_samples() {
|
||||||
|
let blockstore_path = get_tmp_ledger_path!();
|
||||||
|
{
|
||||||
|
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
||||||
|
let num_entries: usize = 10;
|
||||||
|
let mut perf_samples: Vec<(Slot, PerfSample)> = vec![];
|
||||||
|
for x in 1..num_entries + 1 {
|
||||||
|
perf_samples.push((
|
||||||
|
x as u64 * 50,
|
||||||
|
PerfSample {
|
||||||
|
num_transactions: 1000 + x as u64,
|
||||||
|
num_slots: 50,
|
||||||
|
sample_period_secs: 20,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
for (slot, sample) in perf_samples.iter() {
|
||||||
|
blockstore.write_perf_sample(*slot, sample).unwrap();
|
||||||
|
}
|
||||||
|
for x in 0..num_entries {
|
||||||
|
let mut expected_samples = perf_samples[num_entries - 1 - x..].to_vec();
|
||||||
|
expected_samples.sort_by(|a, b| b.0.cmp(&a.0));
|
||||||
|
assert_eq!(
|
||||||
|
blockstore.get_recent_perf_samples(x + 1).unwrap(),
|
||||||
|
expected_samples
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lowest_slot() {
|
fn test_lowest_slot() {
|
||||||
let blockstore_path = get_tmp_ledger_path!();
|
let blockstore_path = get_tmp_ledger_path!();
|
||||||
|
@ -137,6 +137,10 @@ impl Blockstore {
|
|||||||
& self
|
& self
|
||||||
.db
|
.db
|
||||||
.delete_range_cf::<cf::Blocktime>(&mut write_batch, from_slot, to_slot)
|
.delete_range_cf::<cf::Blocktime>(&mut write_batch, from_slot, to_slot)
|
||||||
|
.is_ok()
|
||||||
|
& self
|
||||||
|
.db
|
||||||
|
.delete_range_cf::<cf::PerfSamples>(&mut write_batch, from_slot, to_slot)
|
||||||
.is_ok();
|
.is_ok();
|
||||||
let mut w_active_transaction_status_index =
|
let mut w_active_transaction_status_index =
|
||||||
self.active_transaction_status_index.write().unwrap();
|
self.active_transaction_status_index.write().unwrap();
|
||||||
@ -231,6 +235,10 @@ impl Blockstore {
|
|||||||
&& self
|
&& self
|
||||||
._blocktime_cf
|
._blocktime_cf
|
||||||
.compact_range(from_slot, to_slot)
|
.compact_range(from_slot, to_slot)
|
||||||
|
.unwrap_or(false)
|
||||||
|
&& self
|
||||||
|
.perf_samples_cf
|
||||||
|
.compact_range(from_slot, to_slot)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
compact_timer.stop();
|
compact_timer.stop();
|
||||||
if !result {
|
if !result {
|
||||||
|
@ -51,6 +51,8 @@ const TRANSACTION_STATUS_INDEX_CF: &str = "transaction_status_index";
|
|||||||
const REWARDS_CF: &str = "rewards";
|
const REWARDS_CF: &str = "rewards";
|
||||||
/// Column family for Blocktime
|
/// Column family for Blocktime
|
||||||
const BLOCKTIME_CF: &str = "blocktime";
|
const BLOCKTIME_CF: &str = "blocktime";
|
||||||
|
/// Column family for Performance Samples
|
||||||
|
const PERF_SAMPLES_CF: &str = "perf_samples";
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum BlockstoreError {
|
pub enum BlockstoreError {
|
||||||
@ -137,6 +139,10 @@ pub mod columns {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// The blocktime column
|
/// The blocktime column
|
||||||
pub struct Blocktime;
|
pub struct Blocktime;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
/// The performance samples column
|
||||||
|
pub struct PerfSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum AccessType {
|
pub enum AccessType {
|
||||||
@ -197,7 +203,7 @@ impl Rocks {
|
|||||||
) -> Result<Rocks> {
|
) -> Result<Rocks> {
|
||||||
use columns::{
|
use columns::{
|
||||||
AddressSignatures, Blocktime, DeadSlots, DuplicateSlots, ErasureMeta, Index, Orphans,
|
AddressSignatures, Blocktime, DeadSlots, DuplicateSlots, ErasureMeta, Index, Orphans,
|
||||||
Rewards, Root, ShredCode, ShredData, SlotMeta, TransactionStatus,
|
PerfSamples, Rewards, Root, ShredCode, ShredData, SlotMeta, TransactionStatus,
|
||||||
TransactionStatusIndex,
|
TransactionStatusIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -233,6 +239,8 @@ impl Rocks {
|
|||||||
let rewards_cf_descriptor = ColumnFamilyDescriptor::new(Rewards::NAME, get_cf_options());
|
let rewards_cf_descriptor = ColumnFamilyDescriptor::new(Rewards::NAME, get_cf_options());
|
||||||
let blocktime_cf_descriptor =
|
let blocktime_cf_descriptor =
|
||||||
ColumnFamilyDescriptor::new(Blocktime::NAME, get_cf_options());
|
ColumnFamilyDescriptor::new(Blocktime::NAME, get_cf_options());
|
||||||
|
let perf_samples_cf_descriptor =
|
||||||
|
ColumnFamilyDescriptor::new(PerfSamples::NAME, get_cf_options());
|
||||||
|
|
||||||
let cfs = vec![
|
let cfs = vec![
|
||||||
(SlotMeta::NAME, meta_cf_descriptor),
|
(SlotMeta::NAME, meta_cf_descriptor),
|
||||||
@ -252,6 +260,7 @@ impl Rocks {
|
|||||||
),
|
),
|
||||||
(Rewards::NAME, rewards_cf_descriptor),
|
(Rewards::NAME, rewards_cf_descriptor),
|
||||||
(Blocktime::NAME, blocktime_cf_descriptor),
|
(Blocktime::NAME, blocktime_cf_descriptor),
|
||||||
|
(PerfSamples::NAME, perf_samples_cf_descriptor),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Open the database
|
// Open the database
|
||||||
@ -290,7 +299,7 @@ impl Rocks {
|
|||||||
fn columns(&self) -> Vec<&'static str> {
|
fn columns(&self) -> Vec<&'static str> {
|
||||||
use columns::{
|
use columns::{
|
||||||
AddressSignatures, Blocktime, DeadSlots, DuplicateSlots, ErasureMeta, Index, Orphans,
|
AddressSignatures, Blocktime, DeadSlots, DuplicateSlots, ErasureMeta, Index, Orphans,
|
||||||
Rewards, Root, ShredCode, ShredData, SlotMeta, TransactionStatus,
|
PerfSamples, Rewards, Root, ShredCode, ShredData, SlotMeta, TransactionStatus,
|
||||||
TransactionStatusIndex,
|
TransactionStatusIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -309,6 +318,7 @@ impl Rocks {
|
|||||||
TransactionStatusIndex::NAME,
|
TransactionStatusIndex::NAME,
|
||||||
Rewards::NAME,
|
Rewards::NAME,
|
||||||
Blocktime::NAME,
|
Blocktime::NAME,
|
||||||
|
PerfSamples::NAME,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -542,6 +552,14 @@ impl TypedColumn for columns::Blocktime {
|
|||||||
type Type = UnixTimestamp;
|
type Type = UnixTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SlotColumn for columns::PerfSamples {}
|
||||||
|
impl ColumnName for columns::PerfSamples {
|
||||||
|
const NAME: &'static str = PERF_SAMPLES_CF;
|
||||||
|
}
|
||||||
|
impl TypedColumn for columns::PerfSamples {
|
||||||
|
type Type = blockstore_meta::PerfSample;
|
||||||
|
}
|
||||||
|
|
||||||
impl Column for columns::ShredCode {
|
impl Column for columns::ShredCode {
|
||||||
type Index = (u64, u64);
|
type Index = (u64, u64);
|
||||||
|
|
||||||
|
@ -243,6 +243,13 @@ pub struct AddressSignatureMeta {
|
|||||||
pub writeable: bool,
|
pub writeable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
|
||||||
|
pub struct PerfSample {
|
||||||
|
pub num_transactions: u64,
|
||||||
|
pub num_slots: u64,
|
||||||
|
pub sample_period_secs: u16,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
Reference in New Issue
Block a user