当 Rust ≠ 性能:开发者体验的一课
When rust ≠ performance. a lesson in developer experience

原始链接: https://suriya.cc/tech/performance/oxen-add/

## Oxen 通过代码精简实现性能提升 20 倍 Oxen 是一款数据版本控制工具,致力于追求卓越性能,并定期使用多太字节数据集对命令进行基准测试。虽然 `add` 命令速度很快,但 `commit` 命令即使是一个理论上简单的操作,也需要超过 50 分钟。 性能分析显示,`commit` 命令的 90% 时间都花在了获取暂存 RocksDB 的锁上。根本原因是什么?由于不同代码层之间存在过多的数据克隆和重复的数据库打开,导致线程竞争。尽管职责分离定义明确,但每一层都重复获取相同的文件信息。 一个 PR 消除了这种冗余的数据访问,从而实现了 **20 倍的速度提升**。这凸显了一个关键教训:看似孤立的功能会对整个系统产生影响。此外,团队注意到 RocksDB 针对写入进行了优化,并不适合他们并行且读取密集型的提交过程。这段经历强化了“少即是多”的原则,尤其是在对性能敏感的应用中。

Hacker News 新闻 | 过去 | 评论 | 提问 | 展示 | 招聘 | 提交 登录 当 Rust ≠ 性能:一次开发者体验的教训 (suriya.cc) 9 分,由 suriya-ganesh 1小时前发布 | 隐藏 | 过去 | 收藏 | 2 条评论 binhex 15分钟前 [–] > 但因为这些数据(文件名等)在代码的不同层之间传递。我们做了很多 .clone() 和 db.open() 操作,在不同的层级获取相同的数据。对我来说有趣的部分是,这个改变减少了你们的什么?文章似乎被截断了。回复 taeric 5分钟前 | 父评论 [–] 我猜它原本想说代码行数。它强调删除的代码比添加的代码更多。回复 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系 搜索:
相关文章

原文

getting 20x speedup by removing code.

I love working at oxen because we strive to be the fastest data versioning tool in the market. Which is why we often do multi terabyte benchmarks on each commands that we support , (add, commit, etc.)

All staged files, their location and the file hashes get stored in a rocksdb when oxen add command is used, then during oxen commit we create new nodes for new files/dirs and commit.

I was noting that our add times were pretty quick. ~1 minute for 1M files. But, commit was taking >50 minutes. This was interesting to me because commit is an O(n) algorithm with n = number of directories. we create n directory nodes and 1 commit node, that is all. even with a million files that is not that many directories.

As is usual for all performance work. I profiled the commit command with, samply which is a wildly convenient tool to profile binaries and view it on a nice UI.

Oxen commit perf

If you notice closely, >90% of the time was being spent just getting the lock on the staging RocksDB. This was because all our parallel workers are graduating the files from staged to committed by creating the respective nodes for the directories and creating a complete view of the repository at that commit.

but because we have this data (file name, etc.) passed back and forth between different layers in the code. we were doing lots of .clone() and db.open() at different layers to fetch the same data. The interesting part for me was that, this change reduced our

The final PR looked like this to improve performance by 20X

Oxen commit perf

With performance sensitive application. Often less is more and simple is better.

I often think about this quote from Fabien .

Fabien performance quote

In this case, it was true. In good software engineering fashion, all our layers had clear separation of concerns. Which lead to repeated context retrieval for each thread / async operation leading to thread contention for the same resource. Personally this was a lesson for me on thinking about the Design and impact of the whole system even when adding a seemingly isolated feature.

As an aside it is interesting that, rocksdb is not the ideal candidate for our “parallel reads” use case, because rocksdb is designed for parllel writes. which is why we see this unexpected overhead.

联系我们 contact @ memedata.com