.NET9 Pre7 DATAS+Rustc Compile线程续

点击上方蓝字 江湖评谈设为关注/星标

5ddd98857ec1397692fd7aeb9f6c18b7.png


.NET9 PreView7 DATAS

.NET 9中引入的动态适应应用程序大小(DATAS)功能。DATAS旨在根据应用程序的内存需求自动调整堆大小,使其与长期存活数据的大小大致成正比。这与现有的服务器垃圾回收(Server GC)模式有所不同,后者关注的是提高吞吐量,而不是根据应用程序的大小来调整堆。

DATAS的优势在于:适应不同硬件配置下的应用程序堆大小,使堆大小在不同规格的机器上保持一致或相似。根据工作负载的变化自动调整堆大小,特别是在内存受限的环境中,这有助于在某些进程的工作负载减轻时容纳更多进程。有助于容量规划。

DATAS功能的实现方法包括:

根据长期存活数据的大小设置触发下一次垃圾回收前的最大分配量,以限制堆大小。根据吞吐量设置实际允许的分配量。根据需要调整堆的数量,实现工作站垃圾回收(最少一个堆)和服务器垃圾回收(与机器核心数匹配)之间的混合模式。在需要时执行完全压缩垃圾回收,以防止碎片过多,同时也有助于限制堆大小。

基准测试结果显示,在48核Linux机器上运行基准测试时,工作集显著减少,最大吞吐量(以rps计)降低了约2-3%,但工作集改善了80%以上。启用DATAS后,Gen0和Gen1垃圾回收次数显著增加。

Rust Compile线程详细

继续Rustc的Compile线程,由于llvm或者rustc底板编译器生成的汇编格式在优化之后,一时还不太习惯。一般都类似于这种:

mov rax [rip+0x100]
call rax

而传递的参数,往往是不是rdi,rsi这种,它直接用rip+偏移取代了。这种情况在rustc里面到处都是。

创建一个线程,这里的新线程入口是thread_start,参数是p。:

///rust/library/std/src/sys/pal/unix/thread.rs:84
let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _);

下面的main参数应是上面的p参‍

//library/std/src/sys/pal/unix/thread.rs
extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
    unsafe {
                let _handler = stack_overflow::Handler::new();
                Box::from_raw(main as *mut Box<dyn FnOnce()>)();
            }
            ptr::null_mut()
}

as *mut Box<dyn FnOnce()> 将 main 函数的地址转换为一个指向 Box<dyn FnOnce()> 类型的可变指针。Box::from_raw 是 Rust 标准库中的一个函数,用于从原始指针创建一个 Box<T>。这里它用于从 main 函数的地址创建一个指向 Box<dyn FnOnce()> 的 Box。

FnOnce如下:

// library/core/src/ops/function.rs
#[lang = "fn_once"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
#[rustc_on_unimplemented(
    on(
        Args = "()",
        note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
    ),
    on(
        _Self = "unsafe fn",
        note = "unsafe function cannot be called generically without an unsafe block",
        // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
        label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
    ),
    message = "expected a `{Trait}` closure, found `{Self}`",
    label = "expected an `{Trait}` closure, found `{Self}`"
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
// FIXME(effects) #[const_trait]
pub trait FnOnce<Args: Tuple> {
    /// The returned type after the call operator is used.
    #[lang = "fn_once_output"]
    #[stable(feature = "fn_once_output", since = "1.12.0")]
    type Output;


    /// Performs the call operation.
    #[unstable(feature = "fn_traits", issue = "29625")]
    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

其call_once调用如下:

//library/std/src/sys/backtrace.rs:154
#[inline(never)]
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
where
    F: FnOnce() -> T,
{
    let result = f();
    std::hint::black_box(());
    result
}

这里就体现了上面说的ASM格式,比如f():

0x7ffff0b86530 <+0>:  push   rax
->  0x7ffff0b86531 <+1>:  call   qword ptr [rip + 0x700a7e9]
    0x7ffff0b86537 <+7>:  and    al, 0x1
    0x7ffff0b86539 <+9>:  pop    rcx
    0x7ffff0b8653a <+10>: ret

通过传递的参数调取相应的处理,比如IR变异,机器码生成等等。有的rust函数调用了glibc,比如f(),如果感到疑惑,可以di命令查看其所有汇编代码分析。

往期精彩回顾

Rustc Compile过程+线程

Rust编译器研究+.NET9 PreView7467436d7464896d05557b3481d218331.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值