简体   繁体   English

我的PyV8上下文泄漏内存

[英]My PyV8 contexts leak memory

Whatever I try with PyV8, I always get massive memory leaks. 无论我尝试使用PyV8,总是会出现大量内存泄漏。 Even when executing evals with empty strings, it still seems to leak memory somehow. 即使使用空字符串执行eval,它似乎仍然会以某种方式泄漏内存。 In the example posted below, 10 Million executions of eval with an empty string generate 320MB of memory, of which only 20MB gets collected when explicitly calling the garbage collector afterwards. 在下面发布的示例中,使用空字符串执行的1000万次eval生成320MB的内存,此后在显式调用垃圾回收器时仅会收集20MB的内存。 Whether the context is reachable or not reachable anymore doesn't seem to make a difference for me. 上下文是否可以访问对于我来说似乎并没有什么不同。 I've tested my python itself with a similar test and it doesn't leak memory. 我已经用类似的测试测试了我的python本身,它不会泄漏内存。 Am I doing something wrong? 难道我做错了什么?

Versions 版本

PyV8 Revision 557, built on same machine using PyV8's setup.py PyV8修订版557,使用PyV8的setup.py在同一台计算机上构建

V8 Revision 19632, built on same machine using PyV8's setup.py V8修订版19632,使用PyV8的setup.py在同一台计算机上构建

OS: Ubuntu 12.04 操作系统:Ubuntu 12.04

Test Code 测试代码

import unittest, gc, os, logging as python_logging
from PyV8 import JSEngine, JSContext

_proc_status = '/proc/%d/status' % os.getpid()
_scale = {'kB': 1024.0, 'mB': 1024.0*1024.0,
          'KB': 1024.0, 'MB': 1024.0*1024.0}

def log_memory_usage(intro_text=""):
    python_logging.info(
        (
            '%s process %d now uses %.1f MB resident'
                %(intro_text, os.getpid(), resident()/(1024*1024))
        ).strip()
    )

def _VmB(VmKey):
    '''Private.
    '''
    global _proc_status, _scale
     # get pseudo file  /proc/<pid>/status
    try:
        t = open(_proc_status)
        v = t.read()
        t.close()
    except:
        return 0.0  # non-Linux?
     # get VmKey line e.g. 'VmRSS:  9999  kB\n ...'
    i = v.index(VmKey)
    v = v[i:].split(None, 3)  # whitespace
    if len(v) < 3:
        return 0.0  # invalid format?
     # convert Vm value to bytes
    return float(v[1]) * _scale[v[2]]

def resident(since=0.0):
    '''Return resident memory usage in bytes.
    '''
    return _VmB('VmRSS:') - since   

class TestMemoryWithJSContext(unittest.TestCase):
  def test_python_memory_management(self):
    def inner():
        with JSContext() as ctx:
            log_memory_usage("before empty evals")
            for index1 in range(1000):
                for index2 in range(10000):
                    ctx.eval("")
            log_memory_usage("after empty evals")
            JSEngine.collect()
    log_memory_usage("before JSContext memory tests")
    inner()
    JSEngine.collect()
    gc.collect()
    JSEngine.collect()
    gc.collect()
    log_memory_usage("after JSContext memory tests and gc")
    print "Py gc.garbage:", gc.garbage

class CardEngineTestSuite(unittest.TestSuite):
    def __init__(self):
        super(CardEngineTestSuite, self).__init__()
        self.addTests(unittest.TestLoader().loadTestsFromTestCase(TestPython))
        self.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMemoryWithJSContext))

if __name__ == '__main__':
    python_logging.basicConfig(level=python_logging.INFO, format='%(asctime)s %(message)s')
    unittest.TextTestRunner().run(CardEngineTestSuite())
    unittest.TextTestRunner().run(CardEngineTestSuite())
    python_logging.info(str(gc.garbage))

Output 产量

.2014-03-28 21:41:34,198 before JSContext memory tests process 110 now uses 14.1 MB resident
2014-03-28 21:41:34,199 before empty evals process 110 now uses 14.4 MB resident
2014-03-28 21:41:55,513 after empty evals process 110 now uses 348.8 MB resident
2014-03-28 21:41:56,926 after JSContext memory tests and gc process 110 now uses 322.3 MB resident
Py gc.garbage: []
.
----------------------------------------------------------------------
Ran 2 tests in 26.838s

OK
.2014-03-28 21:42:01,103 before JSContext memory tests process 110 now uses 322.5 MB resident
2014-03-28 21:42:01,104 before empty evals process 110 now uses 322.5 MB resident
2014-03-28 21:42:25,714 after empty evals process 110 now uses 636.5 MB resident
2014-03-28 21:42:28,459 after JSContext memory tests and gc process 110 now uses 629.3 MB resident
Py gc.garbage: []
.
----------------------------------------------------------------------
Ran 2 tests in 31.532s

OK

The answer described in the following PyV8 ticket solved it for me - albeit the garbage collection now takes up a lot of CPU time. 以下PyV8票证中描述的答案为我解决了该问题-尽管垃圾回收现在占用了大量CPU时间。 To get around this I moved my PyV8 code into a celery worker and let it do the garbage collection in the background. 为了解决这个问题,我将我的PyV8代码移到了一个celery worker中,让它在后台进行垃圾收集。 Ping me if you want to see the code for this, right now I'm really out of time to prepare sample code. 如果您想查看此代码,请联系我,现在我真的没有时间准备示例代码。

https://code.google.com/p/pyv8/issues/detail?id=229&sort=-id https://code.google.com/p/pyv8/issues/detail?id=229&sort=-id

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

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