< 返回版块

Mike Tang 发表于 2026-11-06 20:50

gpui-fast 空闲帧降到 0.19ms

《This Month in GPUI》是 GPUI Archipelago 的月报,写 2026 年 9 月和 10 月的 GPUI 生态。作者 Single-Blackberry866 2026 年 10 月 24 日把链接发到 r/rust,采集时 4 分、0 条评论。

上游 Zed 这段时间发了 8 个稳定版,从 v1.18.0 到 v1.25.2,并打开 v1.26.1-pre。v1.25.2 按窗口所在显示器的刷新率计算帧预算。v1.18.0 的 Wayland 渲染循环改成按需唤醒,去掉按刷新率空转。Hang 检测放进 GPUI 自己的监控,release 帧预算是 24ms。官方发布二进制体积在 macOS 上减少 33%,Windows 上减少 28%,Linux 上减少 7%。

官方 crates.io 上的 gpui 仍停在 0.2.2,已经 315 天、523 个 commit 没有新的官方发布。Longbridge 维护者 Jason Lee 用 gpui-pre 重新发布了 Zed 的 GPUI crate,并加了 gpui-kit 门面。Nate Butler 的 gpui-unofficial 镜像现在归 gpui-archipelago,每 6 小时检查上游,按 Zed tag 原样发到 crates.io,当前是 v1.25.2。Zed 曾公开说 9 月底前做自动 crates.io 发布。月报写作时,官方包还没有更新。gpui-pre 和 gpui-unofficial 的对应版本公开项和函数签名一致,可以用 Cargo [patch.crates-io] 收成同一份引擎。

gpui-fast 由 sunli829 写,发在 crates.io,公开 API 不变。它每帧仍重建 immediate-mode 元素树。view 读到的 entity、global,以及 ScrollHandle、ListState 的版本没变时,保留上一帧的 layout、paint range、hitbox、listener 和 primitive。子 view 在干净的父节点里变化时,fast/splice.rs 把更新后的子输出拼进缓存的 primitive 流。拼接条件不满足就整帧重建。window.refresh()、缩放、焦点变化、拖拽、inspector 拾取和无障碍遍历时,保留会关掉。

无头 60 面板基准在同一构建里对比保留开和关。没有面板收到通知时,帧时间从 3.31ms 降到 0.19ms。1 个面板收到通知时,从 6.72ms 降到 0.71ms。60 个都收到通知时,从 10.33ms 降到 7.38ms。滚动和流式基准对照的是 gpui-pre 0.3.7。

bite-gpui 把引擎拆成五个 crate:gpui_types、gpui_platform、gpui_engine、gpui_runtime、gpui_authoring。文本引擎可以换成 gpui_parley。字形图集栅格从每帧 3.3ms 降到 41.1µs。gpui-interop 0.2.0 在 Linux 上把 Vulkan image 导出成 dma-buf,在 Windows 上把 D3D12 共享纹理开到 GPUI 的 D3D11 设备上。macOS 的 IOSurface 到 MTLTexture 还没做。

原文链接:https://gpui-archipelago.github.io/news/october-digest/

redis-rs 2.0.0-rc.1

redis-rs 是 Rust 的 Redis / Valkey 客户端。作者 nihohit 2026 年 10 月 24 日在 r/rust 发了 2.0 发布候选说明,采集时 1 分、7 条评论。crates.io 最新版本是 2.0.0-rc.1,crate 更新时间是 2026-10-24T16:25:39Z。破坏性变更写在 version2.md。文档里的依赖写法是 redis = "2.0.0-rc"。

2.0 默认在 crate 创建的每条 TCP 连接上关闭 Nagle,同步和异步、明文和 TLS 都包括。以前 Nagle 开着。复用连接在并发下,写操作要等 ACK 往返。issue #2195 测到吞吐低 39%–68%,p50 延迟大约翻倍。顺序的请求-响应不受影响。要保留旧行为,用 TcpSettings::default().set_nodelay(false)。

tls-rustls 不再自带根证书库。单独打开 tls-rustls、tokio-rustls-comp 或 smol-rustls-comp 编不过。要同时打开 tls-rustls-native-roots 或 tls-rustls-webpki-roots。issue #2297 写,以前默认的平台证书库会让交叉编译到 Apple 目标失败。两个 store feature 可以一起开,连接信任两边的并集。

整数的 FromRedisValue 不再静默截断。以前 Value::Int 和 Value::Double 用 as 转换,整数回绕,浮点饱和,NaN 变成 0。TTL 对不存在的 key 返回 -2,没有过期时间返回 -1。写成 let ttl: u64 = con.ttl("key")? 会得到 18446744073709551615,不报错。2.0 对表示不了的值返回错误。文档建议改成 i64,再按 -2、-1 和剩余秒数分支。

hmget、hget_ex、geo_hash 的返回类型改成 Vec<Option<String>>,缺字段时不再把整次调用变成类型转换错误。zscore_multiple 从 Option<Vec<f64>> 改成 Vec<Option<f64>>。带分数的 zrange 一类命令统一返回 Vec<(String, f64)>。zrevrange_withscores 以前声明成 Vec<String>。

JsonCommands 并进 TypedCommands 和 Commands。JsonAsyncCommands 并进 AsyncTypedCommands 和 AsyncCommands。Pipeline 里排队 JSON 命令不再返回 RedisResult,调用处要去掉 ?。执行 pipeline 的 ? 还在。

评论里 Puzzleheaded_Gur6922(1 分)写,生产里用过 v1,破坏性变更文档够用来迁移。Sad_Tap_9191(3 分)统计了仓库里的 em dash。作者回复,redis-rs 接受 AI 贡献,每个 PR 由人审。

原文链接:https://github.com/redis-rs/redis-rs/blob/main/version2.md

or_insert 和 or_insert_with 编出同一份汇编

这篇笔记比较 HashMap::entry 的 or_insert 和 or_insert_with。作者 hrubydavid 2026 年 10 月 24 日发到 r/learnrust,并转到 r/rust。r/rust 采集时 0 分、3 条评论。

程序读 10 亿行、413 个 key。每行是 location;measurement。entry 之后 and_modify 更新已有的 MeasurementStats,缺 key 时插入新值。or_insert(MeasurementStats::new(measurement)) 的参数在调用前求值。作者原先以为每一行都会构造一份。改成 or_insert_with 后,闭包只在缺 key 时运行。

location_to_measurement
    .entry(location.to_string())
    .and_modify(|m| m.update(measurement))
    .or_insert_with(|| MeasurementStats::new(measurement));

作者预期每行大约省 4 条指令,10 亿行大约 40 亿条。两次运行的指令数差是 9.8 亿。cargo build --release 之后,cargo asm --bin david david::main --rust 的两份汇编 diff 为空。作者检查汇编,新实例只在 key 不存在时创建。

评论里 Zde-G(3 分)写,LLVM 会内联并删掉用不到的代码。构造过程如果有编译器推不了的副作用,例如访问数据库并写日志,or_insert_with 才会在结果上显出差别。作者提到 clippy 有 clippy::or_fun_call,默认关闭,可以用 cargo clippy -- -W clippy::or_fun_call 打开。

原文链接:https://www.reddit.com/r/learnrust/comments/1xelaqv/rust_gotchas_hashmap_entry_or_insert_or_or_insert/

2000 行 main.rs 怎么拆文件

这是一则关于把单个 main.rs 拆成多个文件的提问。作者 deanominecraft 2026 年 10 月 24 日发到 r/rust,采集时 32 分、18 条评论。side project 大约 2000 行,全写在 main.rs。问题包括 HTTP server 和 client 放一个文件还是多个文件,以及全项目共用的 struct 怎么命名。

Toiling-Donkey(27 分)的做法是,代码多的 struct 单独一个文件,没有方法的 struct 和 enum 放进一个 definitions 文件,目标是 5 个大约 400 行的文件。对外再公开导出,移动文件时其余代码不用改路径。

This_Application1880(18 分)写,先在同一个 crate 里拆 module,共用 struct 放 lib.rs 或 models.rs,需要的再 re-export。编译时间变长之后再拆 crate。这个人自己的 side project 后来变成 7 个 crate 的 workspace,构建脚本还要为 CLI 下载字体。

Dot-Box(6 分)写,2000 行的 main 拆几个文件就够,单个 crate 比 workspace 好管。Fluffy_Disaster_7501(8 分)写,游戏项目按 pg-item 这类 crate 拆开之后,又移回根 src。Compux72(38 分)写了一句 “Multiple files? Rookie mistake, you want to use multiple crates!”,后面补了这句是反话。

原文链接:https://www.reddit.com/r/rust/comments/1xe5zcm/how_to_most_effectively_divide_a_project_into/


From Rust中文社区 Mike

社区学习交流平台订阅:

评论区

写评论

还没有评论

1 共 0 条评论, 1 页