简体   繁体   English

Python:调用函数真的很慢吗?

[英]Python: Calling functions is really slow?

I've got an Element class that has some functions, one like this: 我有一个具有一些功能的Element类,如下所示:

def clean(self):
    self.dirty = False

I have 1024 elements, and I'm calling clean on each one of them in a while 1: loop. 我有1024个元素,并且在while 1:循环中对每个元素调用clean

If I stop calling the clean method, game framerate goes up from 76fps to 250 fps. 如果我停止调用clean方法,则游戏帧率将从76fps上升到250fps。

This is pretty disturbing. 这真令人不安。 Do I really have to be THIS careful not to completely lag out my code? 我真的必须小心不要完全落后于我的代码吗?

Edit (here's the full code) : 编辑(这是完整的代码)

250 fps code 250 fps代码

for layer in self.layers:
            elements = self.layers[layer]
            for element in elements:
                if element.getDirty():
                    element.update()
                    self.renderImage(element.getImage(), element.getRenderPos())

                    element.clean()

76fps code 76fps代码

for layer in self.layers:
            elements = self.layers[layer]
            for element in elements:
                if element.getDirty():
                    element.update()
                    self.renderImage(element.getImage(), element.getRenderPos())

                element.clean()

2Edit (Here's the profiling results): 2编辑(以下是分析结果):

Sat Feb  9 22:39:58 2013    stats.dat

         23060170 function calls (23049668 primitive calls) in 27.845 seconds

   Ordered by: internal time
   List reduced from 613 to 20 due to restriction <20>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
  3720076    5.971    0.000   12.048    0.000 element.py:47(clean)
      909    4.869    0.005   17.918    0.020 chipengine.py:30(updateElements)
  3742947    4.094    0.000    5.443    0.000 copy.py:67(copy)
     4101    3.972    0.001    3.972    0.001 engine.py:152(killScheduledElements)
    11773    1.321    0.000    1.321    0.000 {method 'blit' of 'pygame.Surface' objects}
        4    1.210    0.302    1.295    0.324 resourceloader.py:14(__init__)
  3720076    0.918    0.000    0.918    0.000 element.py:55(getDirty)
     1387    0.712    0.001    0.712    0.001 {built-in method flip}
  3742947    0.705    0.000    0.705    0.000 copy.py:102(_copy_immutable)
  3728284    0.683    0.000    0.683    0.000 {method 'copy' of 'pygame.Rect' objects}
  3743140    0.645    0.000    0.645    0.000 {method 'get' of 'dict' objects}
     5494    0.566    0.000    0.637    0.000 element.py:89(isBeclouded)
     2296    0.291    0.000    0.291    0.000 {built-in method get}
        1    0.267    0.267    0.267    0.267 {built-in method init}
     1387    0.244    0.000   25.714    0.019 engine.py:67(updateElements)
     2295    0.143    0.000    0.143    0.000 {method 'tick' of 'Clock' objects}
    11764    0.095    0.000    0.169    0.000 element.py:30(update)
  8214/17    0.062    0.000    4.455    0.262 engine.py:121(createElement)
       40    0.052    0.001    0.052    0.001 {built-in method load_extended}
    36656    0.046    0.000    0.067    0.000 element.py:117(isCollidingWith)

The profiling says that calling the clean method takes about 6 out of 28 seconds during the profiling. 分析说,在分析过程中,调用clean方法大约需要28秒中的6秒。 It also gets called 3.7 million times during that time. 在此期间,它也被称为370万次。

That means that the loop you are showing must be the main loop of the software. 这意味着您显示的循环必须是软件的主循环。 That main loop also does only the following things: 该主循环还仅执行以下操作:

  1. Checks if the element is dirty. 检查元素是否脏。
  2. If it is, it draws it. 如果是,它将绘制它。
  3. Then cleans it. 然后清洗。

Since most elements are not dirty (update() only gets called 11 thousand of these 3.7 million loops), the end result is that your main loop is now doing only one thing: Checking if the element is dirty, and then calling .clean() on it. 由于大多数元素都不脏(在这370万个循环中,update()仅被调用了11000个),最终结果是您的主循环现在只做一件事:检查元素是否脏,然后调用.clean( ) 在上面。

By only calling clean if the element is dirty, you have effectively cut the main loop in half. 通过仅在元素变脏时调用clean,就可以有效地将主循环切成两半。

Do I really have to be THIS careful not to completely lag out my code? 我真的必须小心不要完全落后于我的代码吗?

Yes. 是。 If you have a very tight loop that for the most time does nothing, then you have to make sure that this loop is in fact tight. 如果您有一个非常紧密的循环,大多数情况下什么都不做,那么您必须确保该循环实际上是紧密的。

This is pretty disturbing. 这真令人不安。

No, it's a fundamental computing fact. 不,这是一个基本的计算事实。

(comment, but my stats are to low to "comment") (评论,但我的统计数据低至“评论”)

If you are calling element.getDirty() 3.7 million times and it's only dirty 11 thousand times, you should be keeping a dirty list, not polling every time. 如果您要调用element.getDirty()370万次,并且仅脏11,000次,则应保留一个脏列表,而不是每次轮询。

That is, don't set the dirty flag, but add the dirty element to a dirty element list. 也就是说,不要设置脏标志,而是将脏元素添加到脏元素列表中。 It looks like you might need a dirty list for each layer. 看来您可能需要为每个图层添加一个脏列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM