来自Erlang Programming(2009):
Erlang并发性快速且可扩展.它的进程是轻量级的,因为Erlang虚拟机不会为每个创建的进程创建一个OS线程.它们在VM中创建,调度和处理,与底层操作系统无关.结果,进程创建时间大约为微秒,并且与并发存在的进程的数量无关.将其与Java和C#进行比较,其中为每个进程创建底层OS线程:您将获得一些非常有竞争力的比较,Erlang大大优于两种语言.
来自Erlang的并发编程(pdf) (幻灯片)(2003):
我们观察到创建Erlang进程所需的时间是1μs到2,500个进程; 此后,对于多达30,000个过程,它增加到大约3μs.Java和C#的性能显示在图的顶部.对于少量过程,创建过程大约需要300μs.创建两千多个流程是不可能的.
我们看到,对于多达30,000个进程,在两个Erlang进程之间发送消息的时间约为0.8μs.对于C#,每个消息大约需要50μs,直到最大进程数(大约1800个进程).Java更糟糕的是,对于多达100个进程,每个消息花了大约50μs,此后当大约有1000个Java进程时,它每个消息迅速增加到10ms.
我并不完全理解为什么Erlang进程在产生新进程方面更有效率,并且每个进程的内存占用量更小.OS和Erlang VM都必须进行调度,上下文切换,并跟踪寄存器中的值等等......
为什么OS线程的实现方式与Erlang中的进程不同?他们还需要支持更多的东西吗?为什么他们需要更大的内存占用?为什么他们的产卵和沟通较慢?
从技术上讲,为什么在产生和通信时,Erlang中的进程比OS线程更有效?为什么操作系统中的线程不能以同样有效的方式实现和管理?为什么操作系统线程的内存占用量更大,产生和通信速度更慢?
正如维基百科所述:
绿色线程模拟多线程环境而不依赖于任何本机操作系统功能,它们在用户空间而不是内核空间中进行管理,使它们能够在没有本机线程支持的环境中工作.
Python的线程实现为pthreads (kernel threads),并且由于全局解释器锁(GIL),Python进程一次只运行一个线程.
[ 问题 ]但在Green-threads(或所谓的greenlet或tasklets)的情况下,
- 这
GIL会影响他们吗?一次可以运行多个greenlet吗?- 使用greenlets或tasklet的缺陷是什么?
- 如果我使用greenlet,进程可以处理多少个?(我想知道,因为在一个进程中你可以打开你的*ix系统中设置的ulimit(-s,-v)线程 .)
我需要一点见解,如果有人可以分享他们的经验,或者引导我走上正确的道路,那将会有所帮助.
forkIO在Haskell中编程时,我习惯于依赖GHC 用于可移植轻量级线程.
什么是C的等效库,可以提供相同的可扩展性和易用性?
具体来说,我需要C等价物至少以下两个功能.
forkIO :: IO () -> IO ThreadId
killThread :: ThreadId -> IO ()
Run Code Online (Sandbox Code Playgroud)
我假设我的应用程序,如果线程只打开阻塞操作而不是被强制挂起就足够了,因为所有线程都经常阻塞网络IO,我只使用splice系统调用要求Linux内核在套接字之间推送数据.
更新
本文比较了数字和表格
结果有利于Protothreads.由于我没有使用过任何其他图书馆,我很乐意听到任何使用/开发此类图书馆的人.
运行时自由:Rust的运行时系统和绿色线程模型已被完全删除,它将"hello world"的静态二进制大小减少了一半,并打开了通向标准库的低级钩子的大门.由Aaron Turon实施.
http://blog.rust-lang.org/2015/01/09/Rust-1.0-alpha.html
绿色线程模型的缺点是什么?
为什么Erlang这么快?
据我所知,Haskell有绿线.但他们的重量有多轻.是否有可能创建100万个线程?
或者10万个线程需要多长时间?
我正在做一些C++绿色线程的研究,大多数boost::coroutine2和类似的POSIX函数一样makecontext()/swapcontext(),并计划在其上实现一个C++绿色线程库boost::coroutine2.两者都需要用户代码为每个新函数/协同程序分配一个堆栈.
我的目标平台是x64/Linux.我希望我的绿色线程库适合一般用途,因此堆栈应该根据需要进行扩展(合理的上限很好,例如10MB),如果堆栈在未使用太多内存时可能会收缩,那就太好了(不需要) ).我还没有想出一个合适的算法来分配堆栈.
经过一些谷歌搜索,我自己想出了几个选项:
mmap()希望内核足够聪明,可以保留未分配的物理内存,只在访问堆栈时分配.在这种情况下,我们受内核的支配.mmap(PROT_NONE)并设置一个SIGSEGV信号处理程序.在信号处理程序中,当SIGSEGV由堆栈访问引起时(被访问的内存在保留的大内存空间内),分配所需的内存mmap(PROT_READ | PROT_WRITE).这是这种方法的问题:mmap()不是异步安全,不能在信号处理程序内部调用.它仍然可以实现,但非常棘手:在程序启动期间为内存分配创建另一个线程,并用于pipe() + read()/write()从信号处理程序向线程发送内存分配信息.关于选项3的更多问题:
mmap()调用而极度分散时,内核/ CPU的性能/坏程度如何?read()被召唤?绿色线程的堆栈分配还有其他(更好的)选项吗?如何在其他实现中分配绿色线程堆栈,例如Go/Java?
我编写了一个小的python应用程序,在这里您可以看到任务管理器在典型运行期间的外观. http://weinzierl.name/temp/multicore-hires.png
虽然应用程序是完全多线程的,但毫不奇怪它只使用一个CPU核心.尽管大多数现代脚本语言都支持多线程,但脚本只能在一个CPU内核上运行.
Ruby,Python,Lua,PHP都只能在单核上运行.即使Erlang,据说对并发编程特别有用,也会受到影响.
是否有一种脚本语言内置支持不限于单个内核的线程?
包起来
答案是并不完全符合我的预期,但在TCL回答接近.我想补充一下perl,(很像TCL)有基于解释器的线程.
Jython,IronPython和Groovy属于将经过验证的语言与另一种语言的成熟虚拟机相结合的保护伞.感谢您对此方向的提示.
我选择Aiden Bell的答案为Accepted Answer.他并没有提出一种特定的语言,但他的评论对我来说最具洞察力.
在阅读了Erlang的轻量级过程后,我非常确定它们是"绿色线程".直到我读到绿色线程和Erlang的进程之间存在差异.但我不明白.
有什么实际差异?
这是测试案例......
import Tkinter as tk
import thread
from time import sleep
if __name__ == '__main__':
t = tk.Tk()
thread.start_new_thread(t.mainloop, ())
# t.iconbitmap('icon.ico')
b = tk.Button(text='test', command=exit)
b.grid(row=0)
while 1:
sleep(1)
Run Code Online (Sandbox Code Playgroud)
这段代码有效.取消注释t.iconbitmap行并锁定.以你喜欢的方式重新安排它; 它会锁定.
当存在图标时,如何防止tk.mainloop锁定GIL?
目标是win32和Python 2.6.2.
我正在研究使用LLVM作为本机代码生成器来设计支持轻量级进程("绿色线程")的并发语言.轻量级进程以M:N方式分配给本机OS线程,并且线程之间的工作窃取应该是可能的(即,进程应该由可以在线程之间传递的数据结构表示,如果需要).可能同时存在大量进程,因此进程不应占用大量内存,并且它们之间的上下文切换应尽可能快.此外,在上下文切换期间或者如果发生垃圾收集,"暂停"轻量级进程应该相当简单.我知道Erlang有一个LLVM后端,但我发现很少有关于它的实现的文献;
programming-languages llvm lightweight-processes green-threads
green-threads ×10
concurrency ×2
erlang ×2
haskell ×2
python ×2
c ×1
c++ ×1
gil ×1
llvm ×1
multicore ×1
networking ×1
pthreads ×1
rust ×1
tkinter ×1
winapi ×1