[openstack-dev] [Keystone] unittests on devstack hosts
Sean Dague
sean at dague.net
Thu Jun 20 00:03:40 UTC 2013
It would strike me as very odd if nose was the culprit (inherently vs.
just poorly written tests). Before nova switched to testr we had over
5000 tests, which is 4x what's in keystone right now.
Also, tempest has > 1000 tests running in nose, and very clearly can
function on a devstack gate node. And we allocate lots of servers to
boot. :)
-Sean
On 06/19/2013 07:22 PM, Brant Knudson wrote:
>
> I was looking into this with Anita Kuno today.
>
> Keystone unit tests would fail when she was running on her vm set up for
> testing. We found that the system was running out of memory. When I run
> it myself, watching memory usage with top, the nosetester process uses
> over 800MB. Anita's vm has 1GB total, and she sent me a screenshot
> showing that the oom killer got it. So it's not that the Keystone unit
> tests don't work in a venv generally -- you need enough of RAM.
>
> Memory use growing without bound indicates a memory leak, so I started
> looking into where references were piling up. I was hoping it would be
> an easy fix where the Keystone test code could be changed to clear a
> list or something. I haven't looked at python memory leaks before so I
> might be wrong on all this, but here's my analysis.
>
> The summary is the references are piling up in the nosetests runner as
> it's storing the results of all the tests, so I don't think there's
> anything we can do in Keystone code to fix it.
>
> I made use of heapy https://pypi.python.org/pypi/guppy/0.1.10 to find
> the heap usage.
>
> After running 872 tests,
>
> > /usr/lib/python2.7/dist-packages/nose/suite.py(223)run()
> -> test(orig)
> (Pdb) p result
> <nose.result.TextTestResult run=869 errors=3 failures=0>
>
> hpy.heap() shows the biggest user of the heap is unnamed dicts.
>
> (Pdb) h1.heap()
> Partition of a set of 487786 objects. Total size = 88365600 bytes.
> Index Count % Size % Cumulative % Kind (class / dict of class)
> 0 76542 16 27581904 31 27581904 31 dict (no owner)
> 1 128620 26 11649056 13 39230960 44 str
> 2 72387 15 6771416 8 46002376 52 tuple
> 3 3043 1 3189064 4 49191440 56 dict of 0x2b96700
> 4 21977 5 2615816 3 51807256 59 list
> 5 20374 4 2444880 3 54252136 61 function
> 6 739 0 2435656 3 56687792 64 dict of
> sqlalchemy.dialects.sqlite.base.SQLiteCompiler
> 7 2579 1 2324312 3 59012104 67 type
> 8 17378 4 2224384 3 61236488 69 types.CodeType
> 9 854 0 2123792 2 63360280 72 dict of module
> <899 more rows. Type e.g. '_.more' to view.>
>
> By running for a while and watching the list change, one sees the "dict
> (no owner)" line start out at the bottom of the list and climb up to the
> top as more tests run.
>
> Digging into the dict data a bit more, one can see what's holding the
> refs to dicts,
>
> (Pdb) h1.heap([0].get_rp(depth=1)
>
> Reference Pattern by <[dict of] class>.
> 0: _ --- [-] 76503 dict (no owner): 0x1a4f150*1673, 0x1a52380*15...
> 1: a [+] 739 dict of
> sqlalchemy.dialects.sqlite.base.SQLiteCompiler: 0x...
> 2: b ---- [+] 514 dict of routes.route.Route: 0x5db1b50..., 0x68f02d0
> 3: c [+] 905 dict of nose.case.Test: 0x2a78490, 0x2ad2c90,
> 0x2ad2e50...
> 4: d ---- [+] 873 dict (no owner): 0x1aaff60*10, 0x1bf9c90*2,
> 0x1f7ef10*34...
> 5: e [S] 157 dict of module: _warnings, errno..., os, sys, zipimport
> 6: f ---- [+] 762 list: 0x2a6e0e0*4, 0x2a6e488*4, 0x2a6e4d0*1,
> 0x2a6e518*1...
> 7: g [+] 146 dict of test_backend_ldap.LDAPIdentity: 0x44b36d0...
> 8: h ---- [+] 146 dict of
> test_backend_ldap.LDAPIdentityEnabledEmulation: 0x...
> 9: i [+] 129 dict of test_backend_sql.SqlIdentity: 0x4522b90,
> 0x50b1290...
>
> If you watch this after running a few more tests, it's the #4 entry
> where the number keeps going up, so looking into this more:
>
> (Pdb) h1.heap()[0].get_rp(depth=1)[4].get_rp()
> Reference Pattern by <[dict of] class>.
> 0: _ --- [-] 873 dict (no owner): 0x1aaff60*10, 0x1bf9c90*2,
> 0x1f7ef10*34...
> 1: a [-] 274 dict (no owner): 0x259c0f0*1, 0x259c420*8,
> 0x25b5a10*1...
> 2: aa ---- [-] 233 dict of
> keystone.catalog.backends.templated.TemplatedCata...
> 3: a3 [-] 233
> keystone.catalog.backends.templated.TemplatedCatalog: 0x...
> 4: a4 ------ [-] 60 dict of test_keystoneclient.KcEssex3TestCase:
> 0x7a20750...
> 5: a5 [-] 60 test_keystoneclient.KcEssex3TestCase: 0x76703d0...
> 6: a6 -------- [-] 60 dict of nose.case.Test: 0x7a17650..., 0x7a17690
> 7: a7 [+] 60 nose.case.Test: 0x6de91d0, 0x6de9210, 0x6de9350...
> 8: a5b ------- [-] 60 dict of unittest2.case._TypeEqualityDict:
> 0x7a20b50...
> 9: a5ba [+] 60 unittest2.case._TypeEqualityDict: 0x6b5bad0...
> <Type e.g. '_.more' for more.>
> (Pdb) h1.heap()[0].get_rp(depth=1)[4].get_rp().more
> 10: a3b ----- [-] 57 dict of test_keystoneclient.Kc11TestCase: 0x7883150...
> 11: a3ba [-] 57 test_keystoneclient.Kc11TestCase: 0x7883150,
> 0x7b43150...
> 12: a3baa ----- [-] 57 dict of nose.case.Test: 0x7a389d0, 0x8394d50...
> 13: a3ba3 [+] 57 nose.case.Test: 0x7a38490, 0x7a385d0, 0x7a389d0...
> 14: a3bab ----- [-] 57 dict of unittest2.case._TypeEqualityDict:
> 0x7b63dd0...
> 15: a3baba [+] 57 unittest2.case._TypeEqualityDict: 0x7883510...
> 16: a3c ----- [-] 31 dict of test_keystoneclient.KcMasterTestCase:
> 0x6dc1490...
> 17: a3ca [-] 31 test_keystoneclient.KcMasterTestCase: 0x6aadc90...
> 18: a3caa ----- [-] 31 dict of nose.case.Test: 0x83225d0, 0x8322610...
> 19: a3ca3 [+] 31 nose.case.Test: 0x83225d0, 0x8322610, 0x8322890...
>
> The smoking gun here is that the source of the references is nose.case.Test.
>
> So I think that the nose runner is keeping references to the the dicts
> that are compared. Also, it looks like nose keeps a reference to the
> test instance (along with any objects created in setUp with self.xxx =
> Xxx()), but this isn't using so much memory as the test dicts.
>
> - Brant
>
> On Mon, Jun 17, 2013 at 6:06 PM, Monty Taylor <mordred at inaugust.com
> <mailto:mordred at inaugust.com>> wrote:
>
> ...
>
> - unittests should always work on a devstack host inside of a venv
>
> I mean, it's a venv - the fact that you're on a devstack machine is
> irrelvant. Btw- apparently keystone and python-keystone client do not
> work in this context - we should probably sort that out.
>
> ...
>
>
> Monty
>
>
>
> _______________________________________________
> OpenStack-dev mailing list
> OpenStack-dev at lists.openstack.org
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
--
Sean Dague
http://dague.net
More information about the OpenStack-dev
mailing list