YJIT: Make yjit_alloc_size available by default (#8426)
This commit is contained in:
parent
721d21d301
commit
ff329ce428
Notes:
git
2023-09-13 14:48:35 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
7
yjit/Cargo.lock
generated
7
yjit/Cargo.lock
generated
@ -34,16 +34,9 @@ version = "0.2.124"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
|
checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stats_alloc"
|
|
||||||
version = "0.1.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5c0e04424e733e69714ca1bbb9204c1a57f09f5493439520f9f68c132ad25eec"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yjit"
|
name = "yjit"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"capstone",
|
"capstone",
|
||||||
"stats_alloc",
|
|
||||||
]
|
]
|
||||||
|
@ -16,13 +16,12 @@ crate-type = ["staticlib"]
|
|||||||
# No required dependencies to simplify build process. TODO: Link to yet to be
|
# No required dependencies to simplify build process. TODO: Link to yet to be
|
||||||
# written rationale. Optional For development and testing purposes
|
# written rationale. Optional For development and testing purposes
|
||||||
capstone = { version = "0.10.0", optional = true }
|
capstone = { version = "0.10.0", optional = true }
|
||||||
stats_alloc = { version = "0.1.10", optional = true }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# NOTE: Development builds select a set of these via configure.ac
|
# NOTE: Development builds select a set of these via configure.ac
|
||||||
# For debugging, `make V=1` shows exact cargo invocation.
|
# For debugging, `make V=1` shows exact cargo invocation.
|
||||||
disasm = ["capstone"]
|
disasm = ["capstone"]
|
||||||
stats = ["stats_alloc"]
|
stats = []
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 0
|
opt-level = 0
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#![allow(dead_code)] // Counters are only used with the stats features
|
#![allow(dead_code)] // Counters are only used with the stats features
|
||||||
|
|
||||||
|
use std::alloc::{GlobalAlloc, Layout, System};
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use crate::codegen::CodegenGlobals;
|
use crate::codegen::CodegenGlobals;
|
||||||
@ -12,13 +14,42 @@ use crate::cruby::*;
|
|||||||
use crate::options::*;
|
use crate::options::*;
|
||||||
use crate::yjit::yjit_enabled_p;
|
use crate::yjit::yjit_enabled_p;
|
||||||
|
|
||||||
// stats_alloc is a middleware to instrument global allocations in Rust.
|
/// A middleware to count Rust-allocated bytes as yjit_alloc_size.
|
||||||
#[cfg(feature="stats")]
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static GLOBAL_ALLOCATOR: &stats_alloc::StatsAlloc<std::alloc::System> = &stats_alloc::INSTRUMENTED_SYSTEM;
|
static GLOBAL_ALLOCATOR: StatsAlloc = StatsAlloc { alloc_size: AtomicUsize::new(0) };
|
||||||
|
|
||||||
|
pub struct StatsAlloc {
|
||||||
|
alloc_size: AtomicUsize,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl GlobalAlloc for StatsAlloc {
|
||||||
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
|
self.alloc_size.fetch_add(layout.size(), Ordering::SeqCst);
|
||||||
|
System.alloc(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||||
|
self.alloc_size.fetch_sub(layout.size(), Ordering::SeqCst);
|
||||||
|
System.dealloc(ptr, layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
||||||
|
self.alloc_size.fetch_add(layout.size(), Ordering::SeqCst);
|
||||||
|
System.alloc_zeroed(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||||
|
if new_size > layout.size() {
|
||||||
|
self.alloc_size.fetch_add(new_size - layout.size(), Ordering::SeqCst);
|
||||||
|
} else if new_size < layout.size() {
|
||||||
|
self.alloc_size.fetch_sub(layout.size() - new_size, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
System.realloc(ptr, layout, new_size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// YJIT exit counts for each instruction type
|
// YJIT exit counts for each instruction type
|
||||||
const VM_INSTRUCTION_SIZE_USIZE:usize = VM_INSTRUCTION_SIZE as usize;
|
const VM_INSTRUCTION_SIZE_USIZE: usize = VM_INSTRUCTION_SIZE as usize;
|
||||||
static mut EXIT_OP_COUNT: [u64; VM_INSTRUCTION_SIZE_USIZE] = [0; VM_INSTRUCTION_SIZE_USIZE];
|
static mut EXIT_OP_COUNT: [u64; VM_INSTRUCTION_SIZE_USIZE] = [0; VM_INSTRUCTION_SIZE_USIZE];
|
||||||
|
|
||||||
/// Global state needed for collecting backtraces of exits
|
/// Global state needed for collecting backtraces of exits
|
||||||
@ -592,8 +623,7 @@ fn rb_yjit_gen_stats_dict(context: bool) -> VALUE {
|
|||||||
hash_aset_usize!(hash, "code_region_size", cb.mapped_region_size());
|
hash_aset_usize!(hash, "code_region_size", cb.mapped_region_size());
|
||||||
|
|
||||||
// Rust global allocations in bytes
|
// Rust global allocations in bytes
|
||||||
#[cfg(feature="stats")]
|
hash_aset_usize!(hash, "yjit_alloc_size", GLOBAL_ALLOCATOR.alloc_size.load(Ordering::SeqCst));
|
||||||
hash_aset_usize!(hash, "yjit_alloc_size", global_allocation_size());
|
|
||||||
|
|
||||||
// `context` is true at RubyVM::YJIT._print_stats for --yjit-stats. It's false by default
|
// `context` is true at RubyVM::YJIT._print_stats for --yjit-stats. It's false by default
|
||||||
// for RubyVM::YJIT.runtime_stats because counting all Contexts could be expensive.
|
// for RubyVM::YJIT.runtime_stats because counting all Contexts could be expensive.
|
||||||
@ -837,13 +867,6 @@ pub extern "C" fn rb_yjit_count_side_exit_op(exit_pc: *const VALUE) -> *const VA
|
|||||||
return exit_pc;
|
return exit_pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the size of global allocations in Rust.
|
|
||||||
#[cfg(feature="stats")]
|
|
||||||
fn global_allocation_size() -> usize {
|
|
||||||
let stats = GLOBAL_ALLOCATOR.stats();
|
|
||||||
stats.bytes_allocated.saturating_sub(stats.bytes_deallocated)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Measure the time taken by func() and add that to yjit_compile_time.
|
/// Measure the time taken by func() and add that to yjit_compile_time.
|
||||||
pub fn with_compile_time<F, R>(func: F) -> R where F: FnOnce() -> R {
|
pub fn with_compile_time<F, R>(func: F) -> R where F: FnOnce() -> R {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user