5 个不稳定版本
0.3.1 | 2023 年 3 月 16 日 |
---|---|
0.3.0 | 2020 年 11 月 2 日 |
0.2.0 | 2020 年 6 月 16 日 |
0.1.2 | 2020 年 4 月 12 日 |
0.1.0 | 2020 年 3 月 20 日 |
#254 在 构建工具
在 crates-io-cli 中使用
240KB
5.5K SLoC
Lean Crate 创新计划
我们希望通过减少下载和解压时间来提高构建时间。这使得对于互联网速度慢的地区或个人来说,生态系统更容易接近,因此对于包容性和扩展 Rust 的范围非常相关。
这通过以下三种方式实现:
- Criner 资源浪费报告 - 分析 crates.io 所有套件的当前版本中的浪费情况,并提供一个 解决方案。
- 'cargo diet' 伴侣程序 - 默认启动时尽可能精简,在发布到 crates.io 之前计算最优的包含和排除项。
- [计划中] 'Lean Crate' 徽章 - 展示你对此事的关心,并在 crates.io 和 README 文件中展示徽章。
动机
我住在中国,学会了与缓慢且不可靠的互联网连接共存。每一个字节到达我的电脑,我都会感到无比的喜悦。
这个倡议是由一个 nushell
更新触发的,这个更新花费了很长时间,在尝试发送 3MB 的图片到 4MB 的下载中失败了多次。这个 修复 非常简单,我好奇还有多少可以通过类似的简单修复来获得。于是产生了 Criner 资源浪费报告 的想法,这很快变成了一系列多步骤的计划来解决这个问题。
如今,nushell
已经 变得非常精简,我希望随着倡议的进行,会有更多的套件是这样的。
你现在如何帮助
首先,非常感谢你愿意提供帮助!让我们开始吧。
前往《Criner Waste Report》查找您的仓库,或者直接使用https://the-lean-crate.github.io/waste/<your-crate>
跳转到您的仓库。查看是否有大量‘waste’被检测到,并验证并尝试建议的修复方案。如果出现问题或无法正常工作,请点击您仓库页面底部的“提供反馈”链接。
示例:有一些‘Waste’需要移除
- 前往您最近发布的仓库版本
- 创建一个新的
include
指令,使用上面页面上建议的值,即include = ["src/**/*", "LICENSE", "README.md", "!**/benches/*"]
。 - 查看它是否对您有效。如果有效,请发布新版本。这将调整下一次Criner作者更新网站时的仓库排名,目前为每天一次。
示例:仓库很精简 - 没有要做的,还是有?
- 前往您最近发布的仓库版本看看仓库是否完美精简!
- 也许检查Criner是否遗漏了什么 - 一种方法是检查它将要上传的包
cargopackage --offline --allow-dirty --no-verify
- 在
target/package
中找到包,并使用以下命令解压:tar -xzf target/package/<crate-version>.crate
。 - 浏览解压后的内容,看看是否比您想象的要多。
- 如果您发现了不需要的文件,并且认为《The Criner Waste Report》应该检测到这些文件,请使用页面底部的“提供反馈”链接并报告问题。
Criner Waste Report
作为《The Lean Crate Initiative》的第一部分,本报告提供了判断是否值得首先解决的问题所需的数据。截至2020-03-18,初步数据显示,在147GB未压缩的仓库数据中,有59GB或40%很可能是构建仓库时不需要的。
报告基于以下假设
- crates.io是Rust源代码的发布平台
- 源代码发布是为了编译仓库,应自包含
基于这些假设,可以得出一些结论。没有必要...
- ……基准测试
- ……测试
- ……文档
- ……测试套件
- ……任何其他用于开发的东西
- (……打包者可以使用来自Github的源存档或克隆存储库以获取运行测试所需的数据)
基于这些假设和结论,本报告计算了新的include
或exclude
指令的建议,这些指令可以防止将不必要的文件放入仓库存档。
由于Cargo处理这些指令的方式,include
指令被认为在保持模式数量小的追求中是最强大的,必要时使用负模式。因此,只要可能,就会推荐这些指令。
本计划的这部分仍然处于快速开发阶段,但目前以“丑陋的alpha版”的形式可用。
请注意,您对这些假设和结论是否正确的反馈非常宝贵,一切都可以根据需要改变,使《Criner Waste Report》在协作、社区驱动的努力中变得更好。
cargo diet
伴侣程序
使用 cargo diet
,您可以在指尖上找到《Criner Waste Report》中所使用的逻辑,即使是在发布第一个crate时,也能轻松开始一个完美的精简crate。
常见问题解答(FAQ)
你怎么敢在我的crate里称任何东西为“废品”?!
抱歉,这个术语是由市场营销部门提出的,他们认为“《Criner Waste Report》会比《Criner Report of files you do not need to build a crate》”表现得更好。
作者确实羞于看到比它们“可能”需要的更大的crate,并乐于帮助您将crate从索引中移除。一些列出的文件肯定是由于局限性导致的误报,请继续阅读本FAQ,了解如何删除这些误报。
它声称我的crate充满了废品,因为它没有看到构建脚本需要的东西?!
确实,Waste Report 会尽力从构建脚本中提取名称,但无法解析像 format!("C-lib-1.0.23-{}", suffix)
这样的事情。要解决这个问题,设置您自己的 include
指令。从那时起,《Criner Waste Report》 将帮助找到更好的包含项,但这仅是一个建议,相信您会以正确的方式设置包含项。
它一直在声称我的包含文件是废品!?
它检测通过 include_str!(…)
和 include_bytes!(…)
包含的文件,但仅限于 lib.rs
和 main.rs
,或其他二进制目标。
我怎样才能让它停止抱怨?
添加它提出的 include = […]
,可能根据您的喜好和需求进行修改。它仍然会为您提供潜在的排除模式,例如测试和文档。
排除指令和包含指令哪个更好?
Waste Report 倾向于包含指令,因为它不会标记任何文件为废品,但会提出如何通过排除测试、文档等来节省更多。
当存在排除指令时,它将建议变为强制性的,并将所有未包含的文件视为废品。原因是白名单,即包含指令,由于存在否定,因此更受 cargo 支持,因此它假设人们对自己的包含项有更好的控制。
“潜在的节省”是什么意思?
这是我们暗示您可以在不改变您设计时的 include
指令的情况下减小crate大小的可能性的一种方式。
然而,目前我们认为某些类型的文件对于构建crate不是必需的,因此可能存在额外的否定模式,这些模式会排除这些文件。常见的例子是测试,这些测试可以通过典型的src/**/*.rs
包含指令轻松包含。
潜在的成本节省不被视为“浪费”,但当前阻止了crate版本达到完美精简
的状态。
Waste报告的限制
- 它只从build.rs文件中提取字符串和'rerun-if'指令。因此,它不太擅长处理运行时生成的字符串或路径。此外,它确实具有过滤逻辑,以减少提取的字符串输入集,这可能导致假阳性。
- 它不处理否定包含模式,但也不会因此受到影响。
- 当用包含模式替换不够具体的排除模式时,它总是解析为所有期望的文件,并且无法从中生成glob模式。这可能导致许多文件建议为包含。
- Cargo遍历整个清单目录并应用其glob集。该glob集中的glob非常贪婪,因此看起来像文件
README.md
实际上会匹配所有匹配*/README.md
或**/README.md
的文件。这可能包括不需要的文件,而我们无法检测到这些文件。您可以通过使用前缀斜杠来规避此问题,例如在/README.md
中,表示该文件必须在顶层。
有趣的事实
- 在一个可敬的5年旧的四核MBP上...
- ...提取所有216k个crate版本(约42GB磁盘空间)大约需要10分钟。这段时间用于提取所有文件元数据和有趣的文件,如Cargo.toml/Cargo.lock、lib.rs和bin.rs,并将这些数据存储在sqlite中。解压缩后将是145GB的数据,因此它每秒处理约240MB。我的感觉是瓶颈在于将结果写入SQLite。
- 生成所有217k个crate版本的报告大约需要3.5分钟,包括每个crate和crates.io的聚合,并将它们写入磁盘。
- 以上两者都只发生一次,因为从那时起所有其他操作都是增量式的,将不必要的工减少到几乎为零。
Criner
Criner是一个平台,使增量挖掘crates.io变得容易且对每个人来说都负担得起。Criner速度快,可配置以使用所有可用的带宽和CPU,同时将内存占用保持在足够低的水平,以便在小于512MB RAM的小型设备上舒适地运行。
它是如何工作的
Criner在执行criner mine
时,目前以三个阶段运行
- 输入
- 新的版本crates-io存储库
- 使用crates.io git索引以增量方式了解新crate
- 计划中 下载crates.io SQL转储以获取更多元数据和下载次数
- 新的版本crates-io存储库
- 处理
- 遍历所有crate版本并计划任务或重新计划失败的任务。如果任务处理器空闲,任务将产生其他任务,以保持所有处理器忙碌。一个处理器是一个轻量级future,通过通道接收任务。一旦任务完成,它就不会再次处理,允许增量处理。
- 任务类型
- 下载 - 下载crate存档并将其存储在磁盘上。截至2020年3月18日,这将需要39GB。
- 提取 - 从内存中提取crate,并存储所有路径元数据,以及一些有趣的文件,例如
Cargo.toml
,完整内容大小不超过128kb。截至2018-03-18,在5年旧的MBPro上处理所有215k个crate版本需要10分钟。 - [计划中] Sloc - 使用tokei进行计数。
- [计划中] Geiger - 使用
cargo geiger
计算不安全代码的数量。
- 报告
- 遍历所有crate版本并为每个版本生成报告文件。聚合crate的所有版本并为每个crate生成报告。聚合所有crate,并为crates.io上的所有crate及其版本生成报告。这通过利用crate版本不可变且只有新版本被添加的事实来实现增量。
- 报告类型
- 浪费 - 聚合构建包不需要的额外文件数量。
- [计划中] Geiger - 显示crate版本中不安全代码的数量,以及可能的依赖项。
- [可能] 速度 - 使用crate及其依赖项的Sloc计数,使用它将为您项目增加多少构建时间(在最坏的情况下)。最小可行产品可能是crate版本及其依赖项的Sloc计数,类似于lib.rs提供的内容。
- 共享
- [计划中] 自动提交 & 推送报告 - 这样,当报告更新时,它们会以最小的延迟推送到GitHub,同时向用户提供进度。
在家运行Criner
克隆此存储库并运行 cargo run --release -- mine
以开始。截至2020-03-18,如果criner被允许完成,它将需要大约46GB的磁盘空间。
Criner for 数据科学
如果已经使用 criner mine
生成了一个数据库,则运行 criner export
以获取另一个SQLite数据库,其中所有数据都已展开到表和字段中,可以使用SQL进行操作。此过程是非增量性的,在单个核心上完成大约需要5分钟。尚未实现多线程。
某些列是 JSON
类型,其属性可以使用 json_*(…)
系列SQLITE函数在查询中。
可能的改进包括导出性能 - 它可能可以并行和增量 - 以及不需要自行挖掘初始数据库状态。Criner可以每天上传其数据库到一个S3存储桶,例如 - 大约800MB的gzip压缩。
操作手册
如何运行迁移
由于迁移目前是特殊目的程序,可能会吃掉洗衣物作为早餐,因此不能意外执行。
RUST_LOG=info cargo run --features migration -- migrate
依赖项
~57–94MB
~1.5M SLoC