当函数移至结构上的方法时,为什么#[inline]属性停止工作?

时间:2020-08-06 22:59:40

标签: rust inline

我具有函数get_screen,它是在与main.rs不同的模块中指定的。它需要两个2D向量(一个1920x1080,称为screen,另一个更大,称为world),并将world向量的一部分映射到screen向量。这是我第一次创建函数签名:

pub fn get_screen(
    screen: &mut Vec<Vec<[u8; 4]>>,
    world: &Vec<Vec<Chunk>>,
    camera_coords: (isize, isize),
    screen_width: usize,
    screen_height: usize,
    chunk_width: usize,
    chunk_height: usize,
)

我在执行时间上遇到了严重的问题,但是我使用#[inline]将执行时间从14ms优化为3ms。

然后我将world向量移到它自己的结构(以及其他一些相关变量,例如块宽度/高度),并将get_screen函数变成新的world结构中的方法。更改后的功能签名如下所示:

pub fn get_screen(
    &self,
    screen: &mut Vec<Vec<[u8; 4]>>,
    camera_coords: (isize, isize),
    screen_width: usize,
    screen_height: usize,
)

然后执行时间增加到14ms。我曾尝试在Cargo.toml中启用lto=true并切换到#[inline(always)]来强制执行它,但似乎编译器拒绝以以前的方式优化此功能。

我试图从结构中删除get_screen方法,并像以前一样将其作为自己的函数运行,并且似乎可以解决该问题,但是如果我不从中传递任何内容,则只能使用 结构。如果我尝试将usize结构中的world传递给单独的get_screen函数,那么执行时间将从3ms增加到14ms。

要显示我的意思的示例,如果我没有直接从world结构传递任何内容,而是向它传递了world中2D结构的克隆版本和硬编码的chunk_width / chunk_height

gen::get_screen(
    &mut screen.buf,
    &cloned_world_data,
    camera_coords,
    SCREEN_WIDTH,
    SCREEN_HEIGHT,
    CHUNK_WIDTH,
    CHUNK_HEIGHT,
);

运行时间为3.3毫秒。当我直接从usize结构中传递chunk_width / chunk_height字段时:

world

运行需要14.55毫秒

这是怎么回事?在使用gen::get_screen( &mut screen.buf, &cloned_world_data, camera_coords, SCREEN_WIDTH, SCREEN_HEIGHT, world.chunk_width, world.chunk_height, ); 结构时,如何使get_screen函数内联编译?最好是,我希望能够将其作为一种方法重新添加到我的World结构中,而不是将其分开。

这是一个最小的示例:

World

1 个答案:

答案 0 :(得分:2)

也许,当您使用world.chunk_widthworld.chunk_height作为参数时,编译器不会将这些参数视为常量,而是实际上会生成除法和模运算。

另一方面,当您为这些参数提供常量时,它们可以在算法中传播(常量折叠),并且不执行某些昂贵的操作(除法,模数)(或转换为移位/掩码)。

在Godbolt(编译器浏览器)中复制/粘贴代码,将separate_test()struct_test()公开,并使用-C opt-level=3进行编译可以确认这一点,因为div指令在为struct_test()生成了代码,但没有为separate_test()生成代码。