英文:
Communicating Sequential Processes in .NET
问题
我最近一直在使用Go语言,突然想到也许将相同的CSP模型构建到未来版本的.NET中是可行的。我不仅仅是在谈论一个提供通道类型和类似编程体验/模型的新库,而是指在整个虚拟机和编译器中实现该模型,以生成与Go相当的可执行代码(我相信Go生成的代码在事件循环上执行)。
这个可行吗?以前有没有讨论过这个问题?...还是我自己想得太多了。对于如何实现这个问题,我显然超出了我的能力范围。
英文:
I have been working with Go recently and it occurred to me that perhaps the same CSP model could be built into a future version of .NET. I'm not simply talking about a new library that provides a channel type and a similar programming experience/model using the existing thread primitives under the hood; I mean implementing the model throughout the VM and compiler to produce executable code that is comparable to Go (I believe Go produces code that executes on an event-loop)
Is this feasible? Has it been talked about before?...or have I been 'drinking too much kool-aid'. I'm definitely way out of my depth on this one in terms of fully understanding how this might be implemented.
答案1
得分: 4
从一个更熟悉Go而不是.NET或Microsoft生态系统的人的角度来写,但尽量使用更嵌入在该领域的资源。
Windows生态系统确实包括一些类似于Go调度器的用户模式任务切换形式:似乎从Windows NT 3.51开始就有纤程,并且作为一个稍微更开发者友好的选项,可以使用用户模式调度来从你自己的代码中调度操作系统线程。据我所知,这两者都没有暴露给.NET(1,2)。
在上面链接的关于纤程的帖子中,Larry Osterman解释了它们在2005年后不再被广泛使用的一些原因。其中一些原因是Windows API中纤程的特定怪癖,但其他原因适用于用户模式调度更普遍的情况。执行上下文切换现在只需要微秒级的时间;除非你期望每秒执行数十万次切换,否则这不是一个问题。而且由于缓存未命中,即使完全在用户模式下执行,切换到在不同数据上操作的不同代码可能已经导致微秒级的延迟。用户线程的收益是很好的,但没有理由认为它们是成败的关键。
在.NET中,你确实有一些不会创建由操作系统管理的线程的异步编程工具,尽管这与用户管理的线程是不同的概念。async
/await
使得在后台运行I/O操作同时进行其他操作更加方便,这与一些使用goroutine进行异步网络操作的用法类似(1,2)。在.NET中,人们尝试使用yield
或async
/await
构建协程,但这并不意味着这是一个好主意。
我很喜欢Go,但就像我建议人们在Go中编写符合惯用法的代码一样,我会说在.NET中编写符合惯用的C#等代码。在这两种情况下,都应该没问题。
如果你发现自己遇到了一个可能涉及线程的问题,你可以随时检查上下文切换统计信息,看看你是否真的做了足够多的切换以至于会有影响,然后如果是的话,回到你的代码中找出如何重新控制事物的方法。担心问题通常比过早担心要好,当你没有可工作的代码时,一切都是理论的!
英文:
Writing this from the perspective of someone more familiar with Go than .NET or Microsoft ecosystems generally, but trying to use sources more embedded in that world.
The Windows ecosystem does include some forms of user-mode task switching similar to what Go's scheduler does: fibers go back to Windows NT 3.51 it seems, and as a slightly more developer-friendly option, user-mode scheduling, can be used to schedule OS threads from your own code. Neither is exposed to .NET as far as I can find (1, 2).
In the post about fibers linked above, Larry Osterman explains some reasons they were no longer heavily used by 2005. Some reasons are specific quirks of fibers in the Windows API, but others apply to user-mode scheduling more generally. Executing a context switch takes microseconds these days; it just isn't a problem unless you're expecting to do hundreds of thousands of switches per second. And because of cache misses, switching to different code operating on different data might already cause delays of microseconds, even if done entirely in user mode. The gains from user threads are nice to have, but there's no reason to assume they're make-or-break.
You do have asynchronous programming tools in .NET that don't create OS-managed threads, though that's a different thing from user-managed threads. async
/await
make it more convenient to have an I/O operation running in the background while you do other stuff, which is similar to some uses of goroutines for asynchronous network stuff (1, 2). In .NET, people have tried to build coroutines on yield
or async
/await
, but that does not mean it's a good idea.
I like Go plenty, but just as I advise folks to write idiomatic Go in Go, I'd say write idiomatic C#, etc. in .NET. In both cases, it's probably gonna be fine.
If you do find yourself with a problem you think might involve threads, you can always check on context switch stats to see if you really are doing enough switches to matter, then if so go back to your code to figure out how you might get things back under control. Worrying later often beats worrying too early, when you don't have working code and it's all theoretical!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论