そんなにがんばる必要は無かった。module gcを使えばよさそう。あとはおのおののobjectのサイズをとって集計してあげないとね。
get_objects( )
現在、追跡しているオブジェクトのリストを返します。このリストには、戻り値のリスト自身は含まれていません。 バージョン 2.2 で 新たに追加 された仕様です。
ただipythonを立ち上げてimport gcしただけでもこれだけobjectがある。もちろん環境による違いはあるだろうが。
In [3]: len(gc.get_objects())
Out[3]: 16033
ところで3.0ではget_objectはviewを返すのだろうか?iterateしてる間に変わりそうだからやはりlistだろう。
Heapyなるものがある。お時間の無い方はどうぞ。ものすごく時間の無い方はこちらにrpmがあります。
自力でやるならこの先はsourceを読むことになるのだが、obmalloc.cにはなかなか素敵なAscii Artがある。
#include "Python.h"
#ifdef WITH_PYMALLOC
/* An object allocator for Python.
Here is an introduction to the layers of the Python memory architecture,
showing where the object allocator is actually used (layer +2), It is
called for every object allocation and deallocation (PyObject_New/Del),
unless the object-specific allocators implement a proprietary allocation
scheme (ex.: ints use a simple free list). This is also the place where
the cyclic garbage collector operates selectively on container objects.
意訳:
これが、pythonのメモリアーキテクチャの階層図です。+2レイヤのallocatorがobjectをalloc/deallocするときに呼ばれます。intとかは「マイ」allocatorを持っていてそれでしょりします。(intの場合はlink list。[訳注:効率のためだと思われる。__slot__なやつらは別途読んでみるといいかもしれない。])cyclic garbage collectorが機能しているレイヤでもある。
+2レイヤでobjectのメモリ消費量を調べないといけない。仮にmemuseというmoduleを作って実現するなら、memuse.size(object)でメモリ消費を返す仕組みにする。
Object-specific allocators
_____ ______ ______ ________
[ int ] [ dict ] [ list ] ... [ string ] Python core |
+3 | <----- Object-specific memory -----> | <-- Non-object memory --> |
_______________________________ | |
[ Python's object allocator ] | |
+2 | ####### Object memory ####### | <------ Internal buffers ------> |
______________________________________________________________ |
[ Python's raw memory allocator (PyMem_ API) ] |
+1 | <----- Python memory (under PyMem manager's control) ------> | |
__________________________________________________________________
[ Underlying general-purpose allocator (ex: C library malloc) ]
0 | <------ Virtual memory allocated for the python process -------> |
=========================================================================
_______________________________________________________________________
[ OS-specific Virtual Memory Manager (VMM) ]
-1 | <--- Kernel dynamic storage allocation & management (page-based) ---> |
__________________________________ __________________________________
[ ] [ ]
-2 | <-- Physical memory: ROM/RAM --> | | <-- Secondary storage (swap) --> |
*/
参考文献。見習いたいものです。
/*==========================================================================*/
/* A fast, special-purpose memory allocator for small blocks, to be used
on top of a general-purpose malloc -- heavily based on previous art. */
/* Vladimir Marangozov -- August 2000 */
/*
* "Memory management is where the rubber meets the road -- if we do the wrong
* thing at any level, the results will not be good. And if we don't make the
* levels work well together, we are in serious trouble." (1)
*
* (1) Paul R. Wilson, Mark S. Johnstone, Michael Neely, and David Boles,
* "Dynamic Storage Allocation: A Survey and Critical Review",
* in Proc. 1995 Int'l. Workshop on Memory Management, September 1995.
*/
/* #undef WITH_MEMORY_LIMITS */ /* disable mem limit checks */
/*==========================================================================*/
デジャブ。ちっこいものに対しては、標準のblockを「ちぎって」小さくallocateする戦略。その昔つとめていた会社でこういうことやっていたなぁ。分割の方針が2nだったけど。
/*
* Allocation strategy abstract:
*
* For small requests, the allocator sub-allocates <Big> blocks of memory.
* Requests greater than 256 bytes are routed to the system's allocator.
*
意訳:
allocatorは小さなメモリ要求に対しては、ブロックから切り出してメモリを割り当てます。256byteよりでかい要求はsystemのallocatorを使います。
* Small requests are grouped in size classes spaced 8 bytes apart, due
* to the required valid alignment of the returned address. Requests of
* a particular size are serviced from memory pools of 4K (one VMM page).
* Pools are fragmented on demand and contain free lists of blocks of one
* particular size class. In other words, there is a fixed-size allocator
* for each size class. Free pools are shared by the different allocators
* thus minimizing the space reserved for a particular size class.
*
意訳:
リクエストは、allocatorが返すアドレスのアライメント都合上、8byte刻みでグループ分けされます。仮想メモリマネジャからもらってきた4KByte blockから1つのグループ用にリストを作ります。リストの生成は必要に応じて行われます。
* This allocation strategy is a variant of what is known as "simple
* segregated storage based on array of free lists". The main drawback of
* simple segregated storage is that we might end up with lot of reserved
* memory for the different free lists, which degenerate in time. To avoid
* this, we partition each free list in pools and we share dynamically the
* reserved space between all free lists. This technique is quite efficient
* for memory intensive programs which allocate mainly small-sized blocks.
意訳:
この割り当て戦略はsimple segregated storage based on array of free lists[あえて訳すなら、リストの配列を用いた単純区分法とかか?]と呼ばれている。この手法の主な欠点はたくさん種類のlist(pool)がおのおのフリーのitemを持つためにメモリlisが消費され、それが時間がたつにつれてひどくなることがあげられる。これを避けるために、poolの間でメモリを共有できるようにする仕組みになっている。ちっこいメモリをたくさんとるようなメモリ郷土の高いプログラムにおいては非常に効果のあるトリックである。
*
* For small requests we have the following table:
*
* Request in bytes Size of allocated block Size class idx
* ----------------------------------------------------------------
* 1-8 8 0
* 9-16 16 1
* 17-24 24 2
* 25-32 32 3
* 33-40 40 4
* 41-48 48 5
* 49-56 56 6
* 57-64 64 7
* 65-72 72 8
* ... ... ...
* 241-248 248 30
* 249-256 256 31
*
* 0, 257 and up: routed to the underlying allocator.
*/
/*==========================================================================*/
/*
* -- Main tunable settings section --
*/
/*
* Alignment of addresses returned to the user. 8-bytes alignment works
* on most current architectures (with 32-bit or 64-bit address busses).
* The alignment value is also used for grouping small requests in size
* classes spaced ALIGNMENT bytes apart.
*
* You shouldn't change this unless you know what you are doing.
*/
意訳:
ユーザに返されるアドレスのアライメント。
やっていることの意味がわからないなら触るべからず。
cpythonだとid()して手に入るものはaddressだからアライメントがどうなっているかを試すといいかもしれません。
#define ALIGNMENT 8 /* must be 2^N */
#define ALIGNMENT_SHIFT 3
#define ALIGNMENT_MASK (ALIGNMENT - 1)
0 件のコメント:
コメントを投稿