最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

從Python的源碼淺要剖析Python的內存管理

 更新時間:2015年04月16日 09:23:02   作者:dbzhang800  
這篇文章主要介紹了從Python的源碼淺要剖析Python的內存管理,需要的朋友可以參考下

Python 的內存管理架構(Objects/obmalloc.c):

復制代碼 代碼如下:

    _____   ______   ______       ________
   [ 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 -------> |
 

    0. C語言庫函數提供的接口

    1. PyMem_*家族,是對 C中的 malloc、realloc和free 簡單的封裝,提供底層的控制接口。

    2. PyObject_* 家族,高級的內存控制接口。
    3. 對象類型相關的管理接口

PyMem_*

PyMem_家族:低級的內存分配接口(low-level memory allocation interfaces)

Python 對C中的 malloc、realloc和free 提供了簡單的封裝:

201541692301579.jpg (301×158)

為什么要這么多次一舉:

  •     不同的C實現對于malloc(0)產生的結果有會所不同,而PyMem_MALLOC(0)會轉成malloc(1).
  •     不用的C實現的malloc與free混用會有潛在的問題。python提供封裝可以避免這個問題。
  •         Python提供了宏和函數,但是宏無法避免這個問題,故編寫擴展是應避免使用宏

源碼:

  Include/pymem.h

#define PyMem_MALLOC(n) ((size_t)(n) > (size_t)PY_SSIZE_T_MAX ? NULL \
             : malloc((n) ? (n) : 1))
#define PyMem_REALLOC(p, n) ((size_t)(n) > (size_t)PY_SSIZE_T_MAX ? NULL \
              : realloc((p), (n) ? (n) : 1))
#define PyMem_FREE free

  Objects/object.c

/* Python's malloc wrappers (see pymem.h) */

void *
PyMem_Malloc(size_t nbytes)
{
  return PyMem_MALLOC(nbytes);
}
...


除了對C的簡單封裝外,Python還提供了4個宏

    PyMem_New 和 PyMem_NEW

    PyMem_Resize和 PyMem_RESIZE

它們可以感知類型的大小

#define PyMem_New(type, n) \
 ( ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL :   \
    ( (type *) PyMem_Malloc((n) * sizeof(type)) ) )

#define PyMem_Resize(p, type, n) \
 ( (p) = ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL :    \
    (type *) PyMem_Realloc((p), (n) * sizeof(type)) )
#define PyMem_Del        PyMem_Free
#define PyMem_DEL        PyMem_FREE


以下涉及的一些函數仍舊是函數和宏同時存在,下劃線后全是大寫字符的是宏,后面不再特別說明。
PyObject_*

PyObject_*家族,是高級的內存控制接口(high-level object memory interfaces)。

    注意

  •     不要和PyMem_*家族混用??!
  •     除非有特殊的內粗管理要求,否則應該堅持使用PyObject_*

源碼

  Include/objimpl.h

#define PyObject_New(type, typeobj) \
        ( (type *) _PyObject_New(typeobj) )
#define PyObject_NewVar(type, typeobj, n) \
        ( (type *) _PyObject_NewVar((typeobj), (n)) )

  Objects/object.c

PyObject *
_PyObject_New(PyTypeObject *tp)
{
  PyObject *op;
  op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
  if (op == NULL)
    return PyErr_NoMemory();
  return PyObject_INIT(op, tp);
}

PyVarObject *
_PyObject_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
{
  PyVarObject *op;
  const size_t size = _PyObject_VAR_SIZE(tp, nitems);
  op = (PyVarObject *) PyObject_MALLOC(size);
  if (op == NULL)
    return (PyVarObject *)PyErr_NoMemory();
  return PyObject_INIT_VAR(op, tp, nitems);
}

它們執(zhí)行兩項操作:

  1.     分配內存:PyObject_MALLOC
  2.     部分初始化對象:PyObject_INIT和PyObject_INIT_VAR

初始化沒什么好看到,但是這個MALLOC就有點復雜無比了...
PyObject_{Malloc、Free}

這個和PyMem_*中的3個可是大不一樣了,復雜的厲害!

void * PyObject_Malloc(size_t nbytes)
void * PyObject_Realloc(void *p, size_t nbytes)
void PyObject_Free(void *p)

Python程序運行時頻繁地需要創(chuàng)建和銷毀小對象,為了避免大量的malloc和free操作,Python使用了內存池的技術。

  •     一系列的 arena(每個管理256KB) 構成一個內存區(qū)域的鏈表
  •     每個 arena 有很多個 pool(每個4KB) 構成
  •     每次內存的申請釋放將在一個 pool 內進行

單次申請內存塊

當申請大小在 1~256 字節(jié)之間的內存時,使用內存池(申請0或257字節(jié)以上時,將退而使用我們前面提到的PyMem_Malloc)。

每次申請時,實際分配的空間將按照某個字節(jié)數對齊,下表中為8字節(jié)(比如PyObject_Malloc(20)字節(jié)將分配24字節(jié))。

復制代碼 代碼如下:

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
         ...                   ...                     ...
       241-248                 248                      30
       249-256                 256                      31
 
       0, 257 and up: routed to the underlying allocator.
      

這些參數由一些宏進行控制:

#define ALIGNMENT        8        /* must be 2^N */
/* Return the number of bytes in size class I, as a uint. */
#define INDEX2SIZE(I) (((uint)(I) + 1) << ALIGNMENT_SHIFT)
#define SMALL_REQUEST_THRESHOLD 256

pool

每次申請的內存塊都是需要在 pool 中進行分配,一個pool的大小是 4k。由下列宏進行控制:

#define SYSTEM_PAGE_SIZE        (4 * 1024)
#define POOL_SIZE               SYSTEM_PAGE_SIZE        /* must be 2^N */

每個pool的頭部的定義如下:

struct pool_header {
  union { block *_padding;
      uint count; } ref;     /* number of allocated blocks  */
  block *freeblock;          /* pool's free list head     */
  struct pool_header *nextpool;    /* next pool of this size class */
  struct pool_header *prevpool;    /* previous pool    ""    */
  uint arenaindex;          /* index into arenas of base adr */
  uint szidx;             /* block size class index    */
  uint nextoffset;          /* bytes to virgin block     */
  uint maxnextoffset;         /* largest valid nextoffset   */
};

注意,其中有個成員 szidx,對應前面列表中最后一列的 Size class idx。這也說明一個問題:每個 pool 只能分配固定大小的內存塊(比如,只分配16字節(jié)的塊,或者只分配24字節(jié)的塊...)。

要能分配前面列表中各種大小的內存塊,必須有多個 pool。同一大小的pool分配完畢,也需要新的pool。多個pool依次構成一個鏈表
arena

多個pool對象使用被稱為 arena 的東西進行管理。

struct arena_object {
  uptr address;
  block* pool_address;
  uint nfreepools;
  uint ntotalpools;
  struct pool_header* freepools;
  struct arena_object* nextarena;
  struct arena_object* prevarena;
};

arean控制的內存的大小由下列宏控制:

#define ARENA_SIZE       (256 << 10)   /* 256KB */

一系列的 arena 構成一個鏈表。
引用計數與垃圾收集

Python中多數對象的生命周期是通過引用計數來控制的,從而實現了內存的動態(tài)管理。

但是引用計數有一個致命的問題:循環(huán)引用!

為了打破循環(huán)引用,Python引入了垃圾收集技術。

相關文章

  • 基于python的列表list和集合set操作

    基于python的列表list和集合set操作

    今天小編就為大家分享一篇基于python的列表list和集合set操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • Python高級技巧之利用psutil和subprocess實現程序監(jiān)控與管理

    Python高級技巧之利用psutil和subprocess實現程序監(jiān)控與管理

    本文介紹了如何使用Python的psutil和subprocess模塊監(jiān)控程序運行狀態(tài),并提供了一個案例腳本,用于監(jiān)控目標程序并在停止時自動重啟,詳細介紹了subprocess模塊的基本用法和psutil模塊的系統(tǒng)信息獲取、進程管理及資源監(jiān)控功能,需要的朋友可以參考下
    2024-09-09
  • Python解析JSON對象的全過程記錄

    Python解析JSON對象的全過程記錄

    這篇文章主要給大家介紹了關于Python解析JSON對象的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • 淺析PEP570新語法: 只接受位置參數

    淺析PEP570新語法: 只接受位置參數

    本文通過一個例子給大家介紹了PEP570新語法: 只接受位置參數的一些知識,感興趣的朋友跟隨小編一起看看吧
    2019-10-10
  • Python3.4解釋器用法簡單示例

    Python3.4解釋器用法簡單示例

    這篇文章主要介紹了Python3.4解釋器用法,結合簡單實例形式分析了Windows與Linux系統(tǒng)環(huán)境中Python3.4解釋器的簡單使用方法,需要的朋友可以參考下
    2019-03-03
  • Django報錯TemplateDoesNotExist的問題及解決

    Django報錯TemplateDoesNotExist的問題及解決

    這篇文章主要介紹了Django報錯TemplateDoesNotExist的問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 詳解?python?logging日志模塊

    詳解?python?logging日志模塊

    這篇文章主要介紹了詳解?python?logging日志模塊,記錄日志最簡單的方法就是在你想要記錄的地方加上一句?print?,?我相信無論是新手還是老鳥都經常這么干。在簡單的代碼中或者小型項目中這么干一點問題都沒有,需要的朋友可以參考下
    2022-01-01
  • python和opencv實現摳圖

    python和opencv實現摳圖

    這篇文章主要為大家詳細介紹了使用python和opencv實現摳圖,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • python 爬取吉首大學網站成績單

    python 爬取吉首大學網站成績單

    python簡單爬蟲,爬取吉首大學成績單,學校的成績單居然不支持導出,太坑了,算個績點居然還要手打,我吐了.花2個多小時寫了此python程序來生成可方便求和平均的Excel文件,幫助JSU學子脫離手算煩惱...
    2021-06-06
  • Python區(qū)塊鏈客戶端類開發(fā)教程

    Python區(qū)塊鏈客戶端類開發(fā)教程

    這篇文章主要為大家介紹了Python區(qū)塊鏈客戶端類開發(fā)教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05

最新評論

拜城县| 慈利县| 罗甸县| 清流县| 尖扎县| 景洪市| 呈贡县| 筠连县| 白玉县| 武宣县| 孝感市| 望奎县| 肥乡县| 松潘县| 友谊县| 翼城县| 汶川县| 承德市| 东莞市| 兰西县| 德钦县| 正定县| 汝州市| 达日县| 阜新市| 天气| 连州市| 卢湾区| 邻水| 文化| 霍州市| 张家界市| 西城区| 丹江口市| 蒙自县| 万全县| 杭锦旗| 龙游县| 黑水县| 开平市| 江孜县|