在迭代器块和异步块中使用元组

3

无论是迭代器还是async方法,都会创建一个状态机来保持yield/await操作之间的状态,您方法中的每个local都变成了该状态机类型实例中的field

这次演讲中,Stephen Toub谈到,在async方法的主体中减少局部变量是一种有效(没有微观)优化,如果您有很多等待调用的话。(即如果您在循环中等待)

因此,在这种情况下,我想知道拥有7个局部变量和拥有一个局部变量(它是Tuple<T1,T2,T3,T4,T5,T6,T7>)之间的性能差异。

显然,如果迭代器中只有一个yield或异步方法中只有一个await,那么它只会使事情变得更加复杂,但是当涉及到数千个或更多时,您认为使用元组(或任何其他类型来包装您的字段)是否有益?
或者,这只是另一种微观优化尝试,没有什么作用或太少使用? 编辑:现在我再次考虑,如果这样做有好处,那么它已经被实现了,我想。尽管如此,我仍然很好奇。

你试过测量这个吗? - svick
1个回答

2
如果你有成千上万个await/yield,那么肯定已经出了很大的问题。需要注意的是,这两者有不同的实现方式。但是,将其更改为元组并没有添加任何有用的东西,在我看来。无论哪种情况,你仍然只存储一个引用(作为状态),无论该引用是:

  • 迭代器实例
  • 捕获变量上下文
  • 元组
  • 捕获变量上下文元组

但是,通过使用元组,你可以保证每次需要改变变量时都需要一个新的实例。

当手动实现异步操作(例如ContinueWith)时,Tulle可能更加有趣,但是在使用编译器提供实现时,我真的不认为这值得。


当我发现“duh?”的答案时,我不确定是否应该删除这个问题:如何使用七个字段初始化一个类可以优化状态机使其具有这些字段?谢谢并+1表示支持 :) - Şafak Gür
顺便问一下,为什么有成千上万个yield就意味着出了问题?如果我对一个有数千个项的集合调用Enumerable.Where会怎样? - Şafak Gür
@safak 如果你的意思是“在循环中”,那么没问题!然而,如果你的意思是你有一个方法使用了一千次“yield”或“await”关键字,那么这个方法似乎做得太多了。 - Marc Gravell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接