6 个稳定版本
1.1.4 | 2020 年 7 月 30 日 |
---|---|
1.1.3 | 2020 年 7 月 13 日 |
1.1.2 | 2020 年 4 月 12 日 |
1.1.1 | 2019 年 12 月 5 日 |
1.0.7 | 2019 年 8 月 27 日 |
#2124 in 命令行工具
29KB
487 行
该程序仅用于在当前生态系统中尝试 async-await 代码。它具有以下功能
- 进行 https 请求
- 一次进行多个请求,每页一个
- 使用异步闭包
代码最初是同步编写的,然后通过非常少的更改移至异步。有趣的是看到 async
构造 允许精确控制并行性,以至于我能够设计相互依赖的未来来匹配数据依赖。这样,当可以并行运行时,事物就会并发运行,这可以通过依赖关系图清晰地表示。
最大的困难在于让 https 工作起来。此外,理解未来的影响显然是一个学习过程。带有 async
的构造 看起来 是同步的,但通过闭包和所有权来展示它们的牙齿。一切都可以解决,只是拥有所有东西,但我认为一旦 async
稳定下来,就会启用更多的借用。
我完全同意的是 异步书籍中的声明,它表明并非所有内容都需要异步。个人而言,我可能会先从 sync
开始,在性能要求改变之前等待转换。然而,我会避免在 未来 使用线程,除非它确实是更简单的解决方案。
我期待看到全异步库的出现,例如,与 git
交互,这可能会比现有库表现得更好。使用 async
库已经是一件轻而易举的事情了!
当考虑这个简单应用的并行性时,已经很明显,人们会想要控制正在执行的未来数量。只需想象对同一主机进行太多并发连接的负面影响,或者操作系统本身强加的资源限制。人们希望有执行者知道他们正在运行什么类型的未来,并限制它们同时运行的数量的数量。
有了 async
,Rust 可以真正改变游戏规则!
安装
cargo install github-star-counter
运行和使用
count-github-stars Byron
count-github-stars --help
一个更完整的示例,展示了速度提升可以有多么巨大。然而,请注意,这也可能导致竞争,例如,存在太多的并发请求,它们一起的速度比单独运行要慢得多。
2019-08-15 08:47:49,553 INFO [github_star_counter] Total bytes received in body: 11.5 MB
2019-08-15 08:47:49,553 INFO [github_star_counter] Total time spent in network requests: 366.84s
2019-08-15 08:47:49,553 INFO [github_star_counter] Wallclock time for future processing: 22.62s
2019-08-15 08:47:49,553 INFO [github_star_counter] Speedup due to networking concurrency: 16.22x
Total: 214379
Total for seanmonstar: 3818
Total for orgs: 210561
mozilla/pdf.js ★ 27611
mozilla/DeepSpeech ★ 10899
mozilla/BrowserQuest ★ 8249
mozilla/send ★ 8165
mozilla/togetherjs ★ 6393
mozilla/nunjucks ★ 6207
tokio-rs/tokio ★ 5598
linkerd/linkerd ★ 5042
hyperium/hyper ★ 5031
linkerd/linkerd2 ★ 4342
➜
开发
git clone https://github.com/Byron/github-star-counter
cd github-star-counter
# Print all available targets
make
所有其他交互都可以通过 cargo
完成。
路上的困难...
请注意,在撰写本文时,即2019年8月13日,生态系统尚未准备就绪。搜索代码中的 TODO
以了解仍然存在的解决方案/问题。
async || {}
(不进行移动)尚未就绪,需要进行移动。这还带来了额外的限制,即无法将引用作为参数传递,它所看到的一切都必须是拥有的。- 支持await的
reqwest
是绝对必要的。我们现在使用的基于hyper的低级别客户端将在GitHub对有效载荷进行gzip压缩后开始失败。目前,我锁定了一个工作的hyper版本,希望它仍然与Tokio一起工作。 - git存储库的锁定并不像我预期的那样简单——我最终创建了具有正确版本的自己的分支。然而,它也应该可以使用
foo = { git = "https://github.com/foo/foo", rev = "hash" }
语法。可能是我的无知。 - 我对像
collect::Result<Vec<Value>, Error>
这样的东西很感兴趣,用于Vec<Future<Output = Result<Value, Error>>>
。join_all
不会在第一个错误时中止,但我认为应该可以根据它实现这样的功能。 - 使用
let mut closure: impl FnMut(User, usize) -> impl Future<Output = Value>
定义闭包似乎不起作用。闭包的返回类型必须是类型参数。
变更日志
对于并行性图表,以 *
为前缀的数据点表示同时处理多个数据。
v1.1.0 - 支持 'tera' 模板
感谢 @mre 的慷慨贡献,现在支持将渲染到自定义 tera 模板。 在此查看示例。
v1.0.6 - 确保正确性
Github 可以静默地调整页面大小,例如,一个人请求每页1000个项目并相应地生成查询,但它只响应100个。现在我们检查并中止,如果给定的页面大小不正确,则提供一个建议的页面大小。当前页面大小似乎限制为100。
v1.0.5 - 更好的性能指标
v1.0.4 - 更好的进展 - 少即是多
只显示汇总结果
v1.0.3 - 更好的进度消息
尽管标题被快速解析和接收,但随后读取正文需要额外的时间。现在这也会被记录。
v1.0.2 - 用户存储库的并行查询更多
并行性看起来是这样的
user-info+---->orgs-info+---->*(user-of-orgs+---->*repo-info-page)
|
|
+---->*repo-info-page
现在,基于数据依赖,已经尽可能地并行了。这实际上非常不错!
v1.0.1 - 用户存储库的并行查询更多
并行性看起来是这样的
user-info+---->orgs-info+-+-->*(user-of-orgs+---->*repo-info-page)
| | ^
| wait | |
+----------------+-----------------------^
我们不等待获取组织用户信息,但在任何进展之前仍然等待组织信息。获取主用户的存储库信息等待时间过长。
v1.0.0 - 初次发布
并行性看起来是这样的
user-info+---->orgs-info+--->*(user-of-orgs-and-main-user+---->*repo-info-page)
参考
这个片段激发了我写一个Rust版本的兴趣。
依赖项
~15–26MB
~380K SLoC