提问人:Filip Pacanowski 提问时间:11/16/2023 最后编辑:Filip Pacanowski 更新时间:11/16/2023 访问量:78
研究带有 Rust 扩展的 Ruby gem 的性能
Investigating the performance of a Ruby gem with Rust extension
问:
介绍
在阅读了 Ruby 优于 C 的文章后,我开始好奇 Rust 的性能如何。因此,我开始研究一个带有 Rust 扩展的 Ruby gem,它实现了 GraphQL 解析器。对于解析器实现,我使用的是 graphql_parser crate。为了与 Ruby 运行时进行交互,我按照本指南使用 magnus。
我的方法
我编写了一些 Rust 代码,这些代码遍历了 AST 生成的 AST 并将其转换为 Ruby 对象(哈希和数组)。代码如下所示:graphql_parser
fn parse(query: String) -> Result<RHash, Error> {
match parse_query::<String>(&query) {
Ok(r) => return Ok(translation::translate_document(&r)),
Err(e) => return Err(Error::new(exception::runtime_error(), e.to_string())),
}
}
fn translate_document(doc: &Document<'_, String>) -> RHash {
let hash = build_ruby_node("document");
let definitions = RArray::new();
for x in doc.definitions.iter() {
definitions.push(translate_definition(x)).unwrap();
}
hash.aset(Symbol::new("definitions"), definitions).unwrap();
return hash;
}
fn translate_definition(definition: &Definition<'_, String>) -> RHash {
return match definition {
Definition::Operation(operation) => translate_operation_definition(operation),
Definition::Fragment(fragment) => translate_fragment_definition(fragment),
};
}
// Many more functions that follow the structure produced by graphql_parser...
fn build_ruby_node(node_type: &str) -> RHash {
let hash = RHash::new();
hash.aset(Symbol::new("node_type"), Symbol::new(node_type))
.unwrap();
return hash;
}
从本质上讲,我有一堆递归函数,它们与 定义的文档结构非常相似。完整代码位于 GitHub 存储库中。graphql_parser
基准
我希望所描述的方法具有类似于以下内容的性能:
fn parse_raw(query: String) -> String {
let ast = parse_query::<&str>(&query);
return format!("#{:?}",ast);
}
我的想法是,这基本上是做同样的事情:遍历 AST 并生成一个具有相同数据的 Ruby 对象。但是,基准测试显示我的代码实际上慢了 ~5 倍:
$ bundle exec ruby benchmark.rb
Warming up --------------------------------------
parse 4.000 i/100ms
parse_raw 24.000 i/100ms
Calculating -------------------------------------
parse 53.968 (± 3.7%) i/s - 272.000 in 5.050661s
parse_raw 245.115 (± 2.4%) i/s - 1.248k in 5.094948s
我用 Ruby 3.2.2 () 运行了这个。ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]
问题
我是 Rust 初学者。我想了解代码中的性能瓶颈在哪里。我做错了什么吗?分配 Ruby 对象本身就很慢吗?有没有办法让这个宝石的性能更高?
答: 暂无答案
评论
format!()
execute(data_to_send_to_graphql)
TypedData_Wrap_Struct
TypedData_Get_Struct