1

我正在使用 Pyglet 用 Python 制作游戏。我刚刚完成了显示部分,并且遇到了速度问题。像一个好人一样,我进行了分析,并得到了以下信息:(排除了无趣的位;目前,当我按下带有随机洋红色和白色的箭头键时,它只是重新绘制屏幕)

    15085326 function calls (15085306 primitive calls) in 32.166 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000   32.168   32.168 <string>:1(<module>)

   120139    0.499    0.000    0.686    0.000 allocation.py:132(alloc)
   120121    0.563    0.000    0.844    0.000 allocation.py:268(dealloc)

       99    0.743    0.008   20.531    0.207 engine.py:58(Update)

   237600    0.796    0.000   11.995    0.000 sprite.py:349(_set_texture)
   120121    0.677    0.000    9.062    0.000 sprite.py:365(_create_vertex_list)
   357721    1.487    0.000    3.478    0.000 sprite.py:377(_update_position)

   420767    0.786    0.000    2.054    0.000 vertexbuffer.py:421(get_region)
   715442    0.859    0.000    1.280    0.000 vertexbuffer.py:467(invalidate)


        1    9.674    9.674   32.168   32.168 win32.py:46(run)
      180    0.007    0.000    1.771    0.010 win32.py:83(_timer_func)


   237600    0.416    0.000   17.069    0.000 window.py:60(SetTile)
   237600    0.646    0.000    2.174    0.000 window.py:72(GetTileTexture)

几乎所有总时间小于 0.5 秒的东西都被删除了。主要是不会有问题的东西。

这是我敲键盘半分钟的结果。在大多数情况下,我每秒可以获得 2 或 3 次屏幕变化。我个人希望尽可能快地敲击键盘。哎呀,我的目标是50-60fps。

win32 运行 10 秒没有花在子功能上,这让我担心。它可能是空闲时间(即使有一个 pyglet 空闲),但这不会花在绘图上吗?

我认为慢的部分实际上是快的;窗口 SetTile 部分。为了处理瓷砖,我有一个 2D 精灵列表,它们在屏幕上代表它们并简单地改变图像。我不认为这是一个问题。

我看到的另一个潜在问题是我的更新——每次调用它时我都必须遍历大约 2400 个图块。然而,这似乎并没有那么糟糕。90 次按键仅需 0.7 秒。

我开始怀疑这是否表明 Python 对我的需求来说太慢了。再说一次,它不应该是。这不是我正在做的计算量太大的事情。

tl; dr Python 中的 win32 事件循环是我的瓶颈吗,这是什么意思?如果没有,我可能在哪里失去了速度?

如果需要,可以使用代码。我假设它是 pyglet 使用的 Pywin32。

4

1 回答 1

2

修订答案:我删除了无价值信息的列,例如自我时间、通话次数和每次通话时间。然后我将它们按cumtime降序排列,并丢弃了小的。

cumtime  filename:lineno(function)
 32.168  <string>:1(<module>)
 32.168  win32.py:46(run)
 20.531  engine.py:58(Update)
 17.069  window.py:60(SetTile)
 11.995  sprite.py:349(_set_texture)
  9.062  sprite.py:365(_create_vertex_list)

Cumtime 表示特定例程在调用堆栈上的总时间。所以很自然地,一些高级例程在堆栈上持续了 32 秒。其他人在堆栈上的时间更短。例如,_set_texture大约 1/3 的时间处于活动状态,而大约 1/3 的时间_create_vertex_list也处于活动状态。这表明顶点被创建了很多,而不是被重复使用,所以也许你可以通过不重新创建它们来节省大约 30% 的时间。

但这只是一个猜测。无需猜测。

您需要知道的是代码中的时间语句(不仅仅是函数)在堆栈上处于活动状态的比例。你需要知道,因为如果出现性能问题,就是这么一行代码。

如果您有问题,以下是如何找到问题的方法。

探查器似乎基于gprof这里有一些关于的评论。

于 2011-04-17T22:19:36.023 回答