- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在编写一个脚本,用于持续(每 30-120 秒)抓取查询大量 URL 的信息(Icecast/Shoutcast 服务器状态页面),大约 500 个 URL。它工作正常,但 python 进程驻留大小不断增长。我确信它会无限增长,因为我让它运行了几个小时,它从最初的 30Mb 占用了 1.2Gb RES。
为了便于理解,我将脚本简化为以下内容:
from twisted.internet import reactor
from twisted.web.client import getPage
from twisted.enterprise import adbapi
def ok(res, url):
print "OK: " + str(url)
reactor.callLater(30, load, url)
def error(res, url):
print "FAIL: " + str(url)
reactor.callLater(30, load, url)
def db_ok(res):
for item in res:
if item[1]:
print "ADDED: " + str(item[1])
reactor.callLater(30, load, item[1])
def db_error(res):
print "Database error: " + str(res)
reactor.stop()
def load(url):
d = getPage(url,
headers={"Accept": "text/html"},
timeout=30)
d.addCallback(ok, url)
d.addErrback(error, url)
dbpool = adbapi.ConnectionPool("MySQLdb", "host", "user", "passwd", db="db")
q = dbpool.runQuery("SELECT id, url FROM stations")
q.addCallback(db_ok).addErrback(db_error)
reactor.run()
它的增长与原始守护进程相同,因此我定位了问题所在。我认为它以某种方式与 twisted.web.client.getPage() 有关。在原始守护程序中,我在运行时使用 twisted.manhole 对 meliae 进行堆评估,但没有看到任何令人讨厌的东西。
仅在完成 1 或 2 个查询周期后立即生成第一个 meliae 转储:
Total 84313 objects, 188 types, Total size = 15.9MiB (16647235 bytes)
Index Count % Size % Cum Max Kind
0 5806 6 4142800 24 24 786712 dict
1 28070 33 2223457 13 38 4874 str
2 612 0 1636992 9 48 3424 HTTPClientFactory
3 19599 23 1585720 9 57 608 tuple
4 643 0 720160 4 61 1120 DelayedCall
5 642 0 713904 4 66 1112 Client
6 617 0 691040 4 70 1120 Connector
7 639 0 577656 3 73 904 type
8 691 0 556576 3 77 1120 Deferred
9 3962 4 475440 2 80 120 function
10 3857 4 462840 2 82 120 code
11 3017 3 308192 1 84 4856 list
12 240 0 266880 1 86 1112 Method
13 2968 3 237440 1 87 80 instancemethod
14 612 0 215424 1 88 352 InsensitiveDict
15 217 0 211128 1 90 12624 module
16 2185 2 157320 0 91 72 builtin_function_or_method
17 107 0 119840 0 91 1120 HTTPPageGetter
18 343 0 117992 0 92 344 IcecastRadioStation
19 343 0 117992 0 93 344 HTTPExtractor
那个时候的顶部:
VIRT RES SHR S %CPU %MEM TIME+ COMMAND
248m 27m 4152 R 92 1.6 0:09.21 python
现在我们等待一段时间再检查,这是运行20分钟后的画面(大约40个查询周期):
Total 67428 objects, 188 types, Total size = 11.9MiB (12463799 bytes)
Index Count % Size % Cum Max Kind
0 3865 5 3601624 28 28 786712 dict
1 23762 35 2002029 16 44 4874 str
2 16382 24 1346208 10 55 608 tuple
3 644 0 582176 4 60 904 type
4 174 0 554304 4 64 3424 HTTPClientFactory
5 456 0 510720 4 68 1120 DelayedCall
6 3963 5 475560 3 72 120 function
7 3857 5 462840 3 76 120 code
8 240 0 266880 2 78 1112 Method
9 237 0 263544 2 80 1112 Client
10 217 0 211128 1 82 12624 module
11 187 0 209440 1 84 1120 Connector
12 182 0 194624 1 85 1120 Deferred
13 1648 2 179696 1 87 3768 list
14 1530 2 122400 0 88 80 instancemethod
15 343 0 117992 0 89 344 IcecastRadioStation
16 343 0 117992 0 90 344 HTTPExtractor
17 1175 1 103400 0 90 88 weakref
18 1109 1 88720 0 91 80 wrapper_descriptor
19 75 0 83400 0 92 1112 InterfaceClass
和顶部:
VIRT RES SHR S %CPU %MEM TIME+ COMMAND
532m 240m 4152 S 54 13.7 4:02.64 python
根据 meliae,对象数量和总大小都没有增长。但是这个进程在这 20 分钟内吃掉了 200Mb 的常驻内存。
我也在python上使用了valgrind,但是没有发现漏洞。有什么想法吗?
我使用的是 Python 版本 2.6.6,扭曲版本 10.2.0
99.93% (578,647,287B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
->94.69% (548,309,283B) 0x550819: O_cwrite (cStringIO.c:406)
| ->94.69% (548,309,283B) 0x55096F: O_write (cStringIO.c:436)
| ->94.69% (548,309,283B) 0x5A17F9: PyCFunction_Call (methodobject.c:81)
| ->94.69% (548,309,283B) 0x4D1373: call_function (ceval.c:3750)
| ->94.69% (548,309,283B) 0x4CC2A2: PyEval_EvalFrameEx (ceval.c:2412)
| ->94.69% (548,309,283B) 0x4D1868: fast_function (ceval.c:3836)
| ->94.69% (548,309,283B) 0x4D1549: call_function (ceval.c:3771)
| ->94.69% (548,309,283B) 0x4CC2A2: PyEval_EvalFrameEx (ceval.c:2412)
| ->94.69% (548,309,283B) 0x4D1868: fast_function (ceval.c:3836)
| ->94.69% (548,309,283B) 0x4D1549: call_function (ceval.c:3771)
| ->94.69% (548,309,283B) 0x4CC2A2: PyEval_EvalFrameEx (ceval.c:2412)
| ->94.69% (548,309,283B) 0x4D1868: fast_function (ceval.c:3836)
| ->94.69% (548,309,283B) 0x4D1549: call_function (ceval.c:3771)
| ->94.69% (548,309,283B) 0x4CC2A2: PyEval_EvalFrameEx (ceval.c:2412)
| ->94.69% (548,309,283B) 0x4D1868: fast_function (ceval.c:3836)
| ->94.69% (548,309,283B) 0x4D1549: call_function (ceval.c:3771)
| ->94.69% (548,309,283B) 0x4CC2A2: PyEval_EvalFrameEx (ceval.c:2412)
| ->94.69% (548,309,283B) 0x4CEBB3: PyEval_EvalCodeEx (ceval.c:3000)
| ->94.69% (548,309,283B) 0x5A0DC6: function_call (funcobject.c:524)
| ->94.69% (548,309,283B) 0x4261E8: PyObject_Call (abstract.c:2492)
| ->94.69% (548,309,283B) 0x4D2870: ext_do_call (ceval.c:4063)
| ->94.69% (548,309,283B) 0x4CC4E3: PyEval_EvalFrameEx (ceval.c:2452)
| ->94.69% (548,309,283B) 0x4CEBB3: PyEval_EvalCodeEx (ceval.c:3000)
| ->94.69% (548,309,283B) 0x5A0DC6: function_call (funcobject.c:524)
| ->94.69% (548,309,283B) 0x4261E8: PyObject_Call (abstract.c:2492)
| ->94.69% (548,309,283B) 0x4D2870: ext_do_call (ceval.c:4063)
| ->94.69% (548,309,283B) 0x4CC4E3: PyEval_EvalFrameEx (ceval.c:2452)
| ->94.69% (548,309,283B) 0x4CEBB3: PyEval_EvalCodeEx (ceval.c:3000)
| ->94.69% (548,309,283B) 0x5A0DC6: function_call (funcobject.c:524)
| ->94.69% (548,309,283B) 0x4261E8: PyObject_Call (abstract.c:2492)
最佳答案
我的猜测是,您是根据固定计时器安排这些页面抓取,而没有注意抓取实际结束的位置。假设获取每个页面需要 60 秒。您有一大堆计划在 30 秒内获取的数据,然后在 30 秒内再次获取,随着您完成较早的请求,越来越多的数据堆积起来。不过,这只是一个猜测,因为即使是这个简化的示例也不是完全独立的。 (您可以在不涉及数据库的情况下仅使用固定的 URL 列表来重现它吗?)
堆栈跟踪也不是特别有用;实际上,它只是说内存是通过调用 python 函数分配的,这应该是显而易见的。你可能想尝试一个特定于 Python 的内存分析器,比如 Heapy或 Dowser查看您的 Python 对象的去向。
关于python - 扭曲的 getPage() : process memory grow when requesting lot of pages,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5432358/
以下代码在2端口上监听,当有消息时修改全局dict对象。并且有一个计时器也会修改字典。 d = {} class x(Protocol): def dataReceived(self, dat
Twisted 怎么样?知道函数应该以异步方式执行吗? 异步函数应该返回一个带有call-/errbacks的Deferred(immeadiately),当收到“异步”数据时将被调用。接收到的数据作
我扭曲了服务器。它与插件一起运行。我想根据请求为每个条目编写唯一的前缀。 这意味着当user1发出请求时,它将生成一个唯一的字符串,该字符串将以日志记录为前缀(仅用于此请求)。当user2发出请求时,
我正在使用校准的立体声对进行稀疏重建。这是我一步一步采取的方法: 1- 我使用 MATLAB 中的立体相机校准器应用程序校准了我的立体相机。 2-我拍摄了一对立体图像,并对每个图像进行了不失真处理。
我关注了这个tutorial但我不知道如何从服务器获取响应数据。 class Service(Resource): def render_POST(self, request):
我的网站上有一个页面,它从数据库中获取大量图像并将它们放在一个网格中。 图像的形状和大小各不相同。 我想要做的是显示图像,每个图像都具有相同的宽度和高度,但不会扭曲。 现在我的CSS是 .image{
我正在尝试创建一个简单的代金券程序。 客户端连接到服务器并询问凭证上是否还有时间,如果是,服务器会响应多少时间。 我控制服务器和客户端,客户端也由我编写代码。 现在这就是我的服务器端,客户端是不言自明
假设我通过 TCP 连接快速接收数据。我必须对其进行某种处理。因为我不想阻塞 react 器线程,所以我将处理卸载到后台线程。 数据到达的速度超过了我处理它的速度。如果我将数据放入队列中,队列会无限增
我有一个简单的客户端,它向服务器发送请求并接收响应: from StringIO import StringIO from twisted.internet import reactor fro
我目前正在使用 python/twisted 构建一个 http 服务器。 该服务器必须在另一个 Web 服务器上获取内容,将其存储在本地并将响应发送回客户端。如果遇到 404,它必须尝试提供本地文件
我有一个扭曲的 react 堆监听传入的数据。我有第二个 react 器在特定时间间隔执行 http 请求,将结果发送到第一个 react 器。两者都运行良好。 现在我想把它放在一起在一个 react
我正在尝试使用 ImageMagick 的透视 功能。我看过这些例子,但我无法理解值对应的是什么。我有这段代码: var stream = new MemoryStream(); using (Mag
我有一个应用程序的想法,该应用程序采用每个角落有四个正方形的打印页面,并允许您在至少有两个正方形可见的情况下测量纸上的对象。我希望能够让用户从不太完美的角度拍照,但仍能准确测量物体。 由于我在该领域缺
我试图让用户在文本框中输入文本,并让程序生成所有可能的组合,但最少 3 个字符和最多 6 个字符除外。我不需要像 ' 这样的无用词as'、'a'、'i'、'to' 等弄乱了我的阵列。我还将根据字典检查
给定一个包含 +ve 和 -ve 整数的数组,找出不允许跳过 2 个连续元素的最大总和(即,您必须至少选择其中一个才能向前移动)。 例如:- 10、20、30、-10、-50、40、-50、-1、-3
什么时候应该使用 twisted.python.failure.Failure,什么时候应该使用 twisted.internet.error.ConnectionDone?或者我应该做 twiste
在 Twisted 中有 1 天的经验,我尝试安排消息发送以回复 tcp 客户端: import os, sys, time from twisted.internet import protocol
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
更新:为了便于阅读,这里是如何在 react 器关闭之前添加回调: reactor.addSystemEventTrigger('before', 'shutdown', callable) 原始问题
所以我已经查看了一些涉及使用 python 和 Twisted 框架编写 HTTP 代理的事情。 基本上,就像其他一些问题一样,我希望能够修改将发送回浏览器的数据。也就是说,浏览器请求资源,代理将获取
我是一名优秀的程序员,十分优秀!