homepage

This issue tracker has been migrated to GitHub , and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: unittest.mock: use slots in MagicMock to reduce memory footprint
Type: resource usage Stage: resolved
Components: Library (Lib) Versions: Python 3.5
process
Status: closed Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: ezio.melotti, james-w, michael.foord, nessita, pitrou, serhiy.storchaka
Priority: normal Keywords:

Created on 2014年08月28日 11:05 by james-w, last changed 2022年04月11日 14:58 by admin. This issue is now closed.

Messages (5)
msg226017 - (view) Author: James Westby (james-w) Date: 2014年08月28日 11:05
Hi,
I'm looking in to the memory usage of our testsuite, which does a fair amount of
 def setUp():
 patcher = patch.multiple(...)
 self.mock_whatever = patcher.start()
 self.addCleanup(patcher.stop)
or other ways of creating a mock and assigning it to an instance variable on a TestCase.
This means that by the end of a run, we have quite a lot of references to MagicMocks.
This then becomes the majority of the memory usage of the python process: (from meliae)
Total 1157176 objects, 1189 types, Total size = 327.1MiB (342972340 bytes)
 Index Count % Size % Cum Max Kind
 0 575750 49 198058000 57 57 344 MagicProxy
 1 49955 4 52034888 15 72 196888 dict
 2 124127 10 11881628 3 76 386477 str
 3 12997 1 11749288 3 79 904 type
 4 8225 0 9146200 2 82 1112 MagicMock
 5 66310 5 5282392 1 84 80056 tuple
 6 38161 3 4579320 1 85 120 function
 7 1503 0 3972281 1 86 49488 module
 8 28506 2 3648768 1 87 128 code
 9 25768 2 2869680 0 88 69168 list
 10 12649 1 2803196 0 89 66356 unicode
 11 2251 0 2503112 0 89 1112 ClientHandler
 12 2228 0 2477536 0 90 1112 _patch
 13 28223 2 2257840 0 91 80 instancemethod
 14 2014 0 2239568 0 91 1112 BoundMethodWeakref
 15 2003 0 2227336 0 92 1112 DummyCache
 16 24681 2 2221112 0 93 792 _CallList
 17 18555 1 1632840 0 93 88 weakref
 18 1457 0 1550248 0 94 1064 Morsel
 19 46258 3 1110192 0 94 24 int
The fact that each MagicMock creates 72 MagicProxies means that it is a significant chunk of memory, despite each being small.
John Arbash Meinel suggested setting __slots__ = ['name', 'parent'] on MagicProxy to reduce the memory usage of this simple object.
This helps with the memory usage:
Total 1140377 objects, 1189 types, Total size = 169.5MiB (177755867 bytes)
 Index Count % Size % Cum Max Kind
 0 47744 4 51347840 28 28 196888 dict
 1 574210 50 36749440 20 49 64 MagicProxy
 2 122020 10 11769659 6 56 386477 str
 3 12975 1 11729400 6 62 904 type
 4 8203 0 9121736 5 67 1112 MagicMock
 5 64125 5 5141368 2 70 80056 tuple
 6 36024 3 4322880 2 73 120 function
 7 1503 0 3972281 2 75 49488 module
 8 28506 2 3648768 2 77 128 code
 9 12643 1 2801540 1 79 66356 unicode
 10 23634 2 2716064 1 80 69168 list
 11 2251 0 2503112 1 82 1112 ClientHandler
 12 28223 2 2257840 1 83 80 instancemethod
 13 2014 0 2239568 1 84 1112 BoundMethodWeakref
 14 2003 0 2227336 1 85 1112 DummyCache
 15 24615 2 2214536 1 87 792 _CallList
 16 18482 1 1626416 0 87 88 weakref
 17 1457 0 1550248 0 88 1064 Morsel
 18 46259 4 1110216 0 89 24 int
 19 2496 0 858624 0 89 344 ModelState
I'm going to go through and drop references so that these can get garbage collected, but making Mock less memory-intensive would probably be appreciated by its users.
Reducing the memory usage of the tiny MagicProxies would be good, but also if there is a way to reduce the number of them by not pre-assiging 72 of them for every MagicMock, when each is very unlikely to be used, then that would be good as well.
Thanks,
James
msg226059 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2014年08月29日 12:41
Switching to Mock instead of MagicMock may help, as that doesn't have the magic proxies at all. (patch has an argument to specify which class of Mock should be used to create the mock object, MagicMock is just the default.)
Other wise using __slots__ would be fine. An alternative approach would be for MagicMock to use __getattribute__ instead of the magic proxies.
msg226241 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2014年09月01日 18:00
> This means that by the end of a run, we have quite a lot of references to MagicMocks.
It sounds like you are bitten by unittest keeping references to all past TestCase instances. This has been fixed recently (see #11798).
msg230486 - (view) Author: Ezio Melotti (ezio.melotti) * (Python committer) Date: 2014年11月02日 14:14
James, could you check again with a recent Python and see if the #11798 fix makes things any better?
msg331640 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018年12月11日 16:19
James, please confirm that this issue still exists in 3.6 and 3.7.
History
Date User Action Args
2022年04月11日 14:58:07adminsetgithub: 66489
2021年12月10日 09:53:20iritkatrielsetstatus: pending -> closed
stage: needs patch -> resolved
2018年12月11日 16:19:46serhiy.storchakasetstatus: open -> pending
nosy: + serhiy.storchaka
messages: + msg331640

2014年11月02日 14:14:47ezio.melottisetnosy: + ezio.melotti
messages: + msg230486
2014年09月01日 18:00:29pitrousetnosy: + pitrou
messages: + msg226241
2014年09月01日 08:55:18rhettingersetstage: needs patch
versions: + Python 3.5, - Python 2.7
2014年08月29日 12:41:25michael.foordsetmessages: + msg226059
2014年08月28日 17:39:35nessitasetnosy: + nessita
2014年08月28日 12:18:24vstinnersetnosy: + michael.foord

title: mock could be less memory-intensive -> unittest.mock: use slots in MagicMock to reduce memory footprint
2014年08月28日 11:05:25james-wcreate

AltStyle によって変換されたページ (->オリジナル) /