- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
如何解决这个内存泄漏问题?
我应该采取什么措施来清理旧的 session 对象?session.close()
还不够吗?
或
和 Pyramid 有关吗?
Sqlalchmey setup:
----------------------------------------------------------------------------------
def get_db(request):
maker = request.registry.dbmaker
session = maker()
@profile
def cleanup(request):
_session = request.db
if request.exception is not None:
_session.rollback()
else:
_session.commit()
_session.close()
# del _session # No memory released
request.add_finished_callback(cleanup)
return session
def main(global_config, **settings):
:
:
config.registry.dbmaker = sessionmaker(bind=engine)
config.add_request_method(get_db, name='db', reify=True)
:
:
Pyramid 应用程序请求处理程序就像
@view_config(route_name='list_employees', renderer='json')
def employees(request):
session = request.db
office = session.query(Office).get(1)
employees = [x.name for x in office.employees]
return employees
现在的问题是,在每个对 list_employees 的请求中,内存都在增长。内存增加的大小几乎等于 office.employees.
调试:
request 1 starts with memory utilization = 10MB
request 1 ends with memory utilization = 18MB
request 2 starts with memory utilization = 18MB
request 2 ends with memory utilization = 26MB
request 3 starts with memory utilization = 26MB
request 3 ends with memory utilization = 34MB
:
:
Grows eventually
employees = [x.name for x in office.employees]
This is the line where about 8-10MB memory utilized
为了调试,我在 Employ 和 Office 模型中添加了 __del__ 方法,看起来它们正在删除。
还尝试了 session.expunge(office)
、del office
和 gc.collect()
我正在使用 https://pypi.python.org/pypi/memory_profiler 调试内存消耗我也在使用 https://pypi.python.org/pypi/transaction是其他请求。
不使用调试 Pyramid 工具栏。
编辑:发现此行的内存增加(employees = [x.name for x in office.employees])在 6-7 次请求后显示为零。但查询返回的行数相同。
编辑:添加了独立应用程序 https://github.com/Narengowda/pyramid_sqlalchemy_app
编辑:它与 SQLALCHEMY 完全无关(我的错)。编写了一个没有任何 sqlalchmey 查询的简单 View 函数。
class Test(object):
def __init__(self):
self.x = 'sdfklhasdjkfhasklsdkjflksdfksd' *1000
self.y = 'sdfklhasdjkfhasklsdkjflksdfksd' *1000
self.z = 'sdfklhasdjkfhasklsdkjflksdfksd' *1000
self.i = 'sdfklhasdjkfhasklsdkjflksdfksd' *1000
self.v = 'sdfklhasdjkfhasklsdkjflksdfksd' *1000
self.o = 'sdfklhasdjkfhasklsdkjflksdfksd' *1000
@view_config(route_name='home', renderer='json')
def my_view(request):
return test(request)
@profile
def test(request):
count = request.GET.get('count')
l = [Test() for i in range(int(count))]
print l[0]
return {}
我能看到这个,下面是请求的日志
Line # Mem usage Increment Line Contents
23 37.3 MiB 0.0 MiB @profile
24 def test(request):
25 37.3 MiB 0.0 MiB count = request.GET.get('count')
26 112.4 MiB 75.1 MiB l = [Test() for i in range(int(count))]
27 112.4 MiB 0.0 MiB print l[0]
28 112.4 MiB 0.0 MiB return {}
Line # Mem usage Increment Line Contents
23 111.7 MiB 0.0 MiB @profile
24 def test(request):
25 111.7 MiB 0.0 MiB count = request.GET.get('count')
26 187.3 MiB 75.6 MiB l = [Test() for i in range(int(count))]
27 187.3 MiB 0.0 MiB print l[0]
28 187.3 MiB 0.0 MiB return {}
Line # Mem usage Increment Line Contents
23 184.3 MiB 0.0 MiB @profile
24 def test(request):
25 184.3 MiB 0.0 MiB count = request.GET.get('count')
26 259.7 MiB 75.4 MiB l = [Test() for i in range(int(count))]
27 259.7 MiB 0.0 MiB print l[0]
28 259.7 MiB 0.0 MiB return {}
Line # Mem usage Increment Line Contents
23 255.1 MiB 0.0 MiB @profile
24 def test(request):
25 255.1 MiB 0.0 MiB count = request.GET.get('count')
26 330.4 MiB 75.3 MiB l = [Test() for i in range(int(count))]
27 330.4 MiB 0.0 MiB print l[0]
28 330.4 MiB 0.0 MiB return {}
Line # Mem usage Increment Line Contents
23 328.2 MiB 0.0 MiB @profile
24 def test(request):
25 328.2 MiB 0.0 MiB count = request.GET.get('count')
26 330.5 MiB 2.3 MiB l = [Test() for i in range(int(count))]
27 330.5 MiB 0.0 MiB print l[0]
28 330.5 MiB 0.0 MiB return {}
Line # Mem usage Increment Line Contents
23 330.5 MiB 0.0 MiB @profile
24 def test(request):
25 330.5 MiB 0.0 MiB count = request.GET.get('count')
26 330.5 MiB 0.0 MiB l = [Test() for i in range(int(count))]
27 330.5 MiB 0.0 MiB print l[0]
28 330.5 MiB 0.0 MiB return {}
我用不同的计数查询参数尝试了很多次,发现内存利用率的增加在恰好 5 个请求后停止(神奇)。
我还尝试打印所有对象并比较那里的地址我观察到的是查看请求 4 和 5 的日志。看起来 GC 发生了,因此内存从 330.4 Mi 减少到 328.2 MiB但是您不会看到 75.3 MiB 内存使用率来创建新对象(第 26 行),但您只会看到 2.3 MiB 的增加。后来我验证了前两次请求中创建的对象地址,发现前两次请求中80%的对象地址是相同的
<pyramid_sqa.views.Test object at 0x3a042d0>
<pyramid_sqa.views.Test object at 0x3a04310>
<pyramid_sqa.views.Test object at 0x3a04350>
<pyramid_sqa.views.Test object at 0x3a04390>
<pyramid_sqa.views.Test object at 0x3a043d0>
<pyramid_sqa.views.Test object at 0x3a04410>
<pyramid_sqa.views.Test object at 0x3a04450>
<pyramid_sqa.views.Test object at 0x3a04490>
<pyramid_sqa.views.Test object at 0x3a044d0>
<pyramid_sqa.views.Test object at 0x3a04510>
<pyramid_sqa.views.Test object at 0x3a04390>
<pyramid_sqa.views.Test object at 0x3a043d0>
<pyramid_sqa.views.Test object at 0x3a04410>
<pyramid_sqa.views.Test object at 0x3a04450>
<pyramid_sqa.views.Test object at 0x3a04490>
<pyramid_sqa.views.Test object at 0x3a044d0>
<pyramid_sqa.views.Test object at 0x3a04290>
<pyramid_sqa.views.Test object at 0x3a04550>
<pyramid_sqa.views.Test object at 0x3a04590>
<pyramid_sqa.views.Test object at 0x3a045d0>
因此创建了新对象并且 python 正在重用内存(重用对象!!?)
如果我的服务器内存像这样猛增,可以吗?
最佳答案
Python 对 Python 对象进行自己的内存管理,即使 CPython GC 释放了 Python 对象,它仍然不会将内存释放给操作系统(就像 malloc()/free() 可能做的那样)。当 GC 释放一个 Python 对象时,内存可以用于新的 Python 对象。这是您在请求编号 6 的内存消耗没有增加时看到的效果。在编号 5 之后,GC 释放了已删除的对象,请求编号 6 中的新对象可以使用释放的内存。
所以你没有内存泄漏,你只是发现了 CPython 内存管理的工作原理。内存消耗不会无限制地增长。
关于python-pyramid 应用程序内 stub 本没有释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25200475/
Pyramid 项目中有一个 development.ini 或 production.ini 。我将自己的配置数据添加到 ini 文件如: [thrift] host = 0.0.0.0 port
我想注册一个请求处理程序,但不想使用扫描方法。 为什么我需要调用两个方法(add_route 和 add_view)而不是一个? from wsgiref.simple_server import m
请问我错过了什么。当我想提供已下载到磁盘上的视频文件时,我不断在浏览器中收到内部服务器错误。这是我的代码: View 函数 @view_config(name='download_video') de
请问我错过了什么。当我想提供已下载到磁盘上的视频文件时,我不断在浏览器中收到内部服务器错误。这是我的代码: View 函数 @view_config(name='download_video') de
我目前正在学习如何使用 Python Pyramid Web 框架,并且发现文档非常出色。 然而,在区分“模型”(即在 SQLAlchemy 声明性系统下定义的类)的概念和“资源”(即定义访问控制的方
我一直在尝试让 Pyramid 在谷歌应用程序引擎中运行,但没有成功。我尝试按照说明 here 进行操作但它似乎已经过时了,因为 gae 不再有 appcfg.py 了。我按照应用程序引擎文档中的 F
大多数可用教程都展示了如何使用上游 HTTP 服务器(如 NGINX)设置 uWSGI。但是 uWSGI 本身就可以完美地充当路由器/代理/负载均衡器 - 请参阅 this对于我的项目,我现在不想设置
我正在尝试使用 Pyramid 自省(introspection)接口(interface)从可调用 View 中获取给定资源类型的所有 View 的列表。我可以使用以下方法获取一组已添加的 View
我正在使用 Pyramid 来创建网络应用程序。然后我使用 Pyramid 烧杯将烧杯连接到 Pyramid 的 session 管理系统。 有两个值会影响用户 session 的持续时间。 sess
背景 我对 unicode 和 Python 真是一团糟。这似乎是一个普遍的焦虑,我尝试过使用其他解决方案,但我就是无法解决这个问题。 设置 MySQL 数据库设置 collation_datab
模型 - View - PHP 框架(如 Kohana)的 Controller 的 Pyramid/Python 等价物是什么? In Pyramid "Model" is .... and it
我遵循了 http://docs.pylonsproject.org/docs/pyramid/en/latest/tutorials/wiki/index.html 上的教程 我知道,当我添加或更改
我使用 yapps 为 Pyramid 内的 LaTex 语言生成解析器(例如将 \begin{itemize} 之类的内容翻译成相应的 -Tags)。一个命令(即 \ref{SOMEID} )应该
我正在 Pyramid 框架之上使用 python 制作 webapps。 在我利用 Mechanize 进行一些简单网页抓取的函数之一中,当我将其作为独立的 Python 脚本运行并通过 Pyram
var z = []; for(var i = 1; i len) z.push("a".repeat(len-i%len)) console.log(z.join("\n")); 关于jav
我正在开发 Python Pyramid我需要使用rest api,在其中一个请求中,我需要处理一个excel,对于它的每一行,我都会获取GPS坐标并进行大量验证,这意味着这个唯一的请求可能需要大约1
这是我的 base.html: {% block head %} {% endblock %} {% block body
我一直在尝试使用 Pyramid 框架制作带有复选框和单选按钮的表单,但我不知道如何正确执行。 我正在使用pyramid_simpleform。到目前为止,我已经能够使用 for 循环将复选框放在表单
我按照 Pyramid 教程进行操作,一切正常。然后我为 Pyramid 安装了 jinja2,并将必要的代码行添加到我的 development.ini 文件中。按预期在指定位置找到了我的模板。它们
我的应用程序从用户接收一个或多个 URL(通常为 3-4 个 URL),从这些 URL 中抓取某些数据并将这些数据写入数据库。但是,因为抓取这些数据需要一点时间,所以我正在考虑在单独的线程中运行每个抓
我是一名优秀的程序员,十分优秀!