我将使用Stackless Python做什么?

时间:2010-02-08 09:48:13

标签: python python-stackless

有许多与Stackless Python相关的问题。但没有人回答我的问题,我想(如果错了,请纠正我 - 拜托!)。有一些关于它的嗡嗡声所以我很想知道。我会用Stackless做什么用的?它比CPython好吗?

是的,它有绿色线程(无堆栈),只要没有操作阻塞(像Ruby的线程那样?),它就可以快速创建许多轻量级线程。这个有什么用?它有什么其他功能我想用于CPython?

6 个答案:

答案 0 :(得分:29)

它允许您使用大量并发。没人理智会创建十万个系统线程,但你可以使用无堆栈来完成。

本文测试了这一点,在Python和Google Go(一种新的编程语言)中创建了十万个tasklet:http://dalkescientific.com/writings/diary/archive/2009/11/15/100000_tasklets.html

令人惊讶的是,即使Google Go被编译为本机代码,并且他们也在宣传他们的协同例程,Python仍然会获胜。

Stackless适用于实现map / reduce算法,根据输入数据,你可以拥有大量的reducer。

答案 1 :(得分:12)

Stackless Python的主要好处是支持非常轻量级的协同程序。 CPython本身并不支持协同程序(虽然我希望有人在评论中发布基于生成器的hack)所以当你遇到一个从协同程序中受益的问题时,Stackless是对CPython的明显改进。

我认为他们擅长的主要领域是当您在程序中运行许多并发任务时。示例可能是为其AI运行循环脚本的游戏实体,或者为许多客户端提供创建速度慢的页面的服务器。

然而,对于共享数据,您仍然存在许多典型的并发正确性问题,但确定性任务切换使得编写安全代码变得更加容易,因为您确切知道控件将在何处传输,因此知道共享的确切位置国家必须是最新的。

答案 2 :(得分:8)

Thirler已经提到在Eve Online中使用了stackless。请记住:

  

(..)stackless通过允许将任务分成较小的任务Tasklet来进一步加剧这一点,然后可以将它们从主程序中分离出来以便自己执行。这可以用于即发即弃任务,例如发送电子邮件,调度事件,或用于IO操作,例如,发送和接收网络数据包。一个tasklet等待来自网络的数据包,而其他任务继续运行游戏循环。

     

它在某些方面类似于线程,但是非抢占式和明确调度,因此同步问题较少。此外,在tasklet之间切换要比线程切换快得多,并且你可以拥有大量活动的tasklet,而线程的数量则受到计算机硬件的严格限制。

(从here获得此引文)

在PyCon 2009上,给出了a very interesting talk,描述了在CCP Games中使用Stackless的原因和方式。

此外,还有一个非常好的introductory material,它描述了无堆栈为您的应用程序提供良好解决方案的原因。 (可能有些陈旧,但我认为值得一读。)

答案 3 :(得分:6)

EVEOnline主要在Stackless Python中编程。他们有几个关于使用它的开发博客。它似乎对高性能计算非常有用。

答案 4 :(得分:6)

虽然我没有使用Stackless本身,但我使用Greenlet来实现高度并发的网络应用程序。 Linden实验室的一些使用案例包括:高性能智能代理,用于在大量机器上分配命令的快速系统,以及执行大量数据库写入和读取的应用程序(比率约为1) :2,这是非常重写的,所以它花费大部分时间等待数据库返回),以及内部Web数据的web-crawler-type-thing。基本上任何期望必须执行大量网络I / O的应用程序都将受益于能够创建bajillion轻量级线程。 10,000个连接的客户对我来说似乎不是什么大不了的事。

然而,

Stackless或Greenlet并不是一个完整的解决方案。它们是非常低级的,你将不得不做很多的猴子工作来与他们一起构建一个充分利用它们的应用程序。我知道这是因为我维护了一个库,它在Greenlet之上提供了一个网络和调度层,特别是因为使用它编写应用程序非常容易。现在有很多这样的;我维护了Eventlet,但也有Concurrence,Chiral,还有一些我不知道的东西。

如果您要编写的应用程序类似于我所写的内容,请考虑其中一个库。 Stackless vs Greenlet的选择与决定哪个库最适合您想要做的事情相比,不那么重要。

答案 5 :(得分:5)

绿色线程的基本用途,就像我看到的那样,是实现一个系统,在这个系统中你有大量的对象进行高延迟操作。一个具体的例子是与其他机器通信:

def Run():
    # Do stuff
    request_information() # This call might block
    # Proceed doing more stuff

线程允许您自然地编写上面的代码,但是如果对象的数量足够大,则线程无法充分执行。但是你可以使用绿色线程,即使是非常大的数量。上面的request_information()可以切换到某个调度程序,其他工作正在等待并稍后返回。您可以获得能够调用“阻止”函数的所有好处,就像它们立即返回而不使用线程一样。

如果您想以直接的方式编写代码,这显然对任何类型的分布式计算都非常有用。

多个核心可以缓解等待锁定的问题:

def Run():
    # Do some calculations
    green_lock(the_foo)
    # Do some more calculations

green_lock函数基本上会尝试获取锁,如果由于其他核使用该对象而失败,则只切换到主调度程序。

同样,绿色线程被用于缓解阻塞,允许代码自然地编写并且仍然表现良好。