zoukankan      html  css  js  c++  java
  • Python源码学习之初始化(三)-PyDictObject的初始化

    先来看它的定义
    typedef struct _dictobject PyDictObject;
    struct _dictobject {
        PyObject_HEAD
        Py_ssize_t ma_fill;  /* # Active + # Dummy */
        Py_ssize_t ma_used;  /* # Active */
    
        /* The table contains ma_mask + 1 slots, and that's a power of 2.
         * We store the mask instead of the size because the mask is more
         * frequently needed.
         */
        Py_ssize_t ma_mask;
    
        /* ma_table points to ma_smalltable for small tables, else to
         * additional malloc'ed memory.  ma_table is never NULL!  This rule
         * saves repeated runtime null-tests in the workhorse getitem and
         * setitem calls.
         */
        PyDictEntry *ma_table;
        PyDictEntry *(*ma_lookup)(PyDictObject *mp, PyObject *key, Py_hash_t hash);
        PyDictEntry ma_smalltable[PyDict_MINSIZE];
    };
    
    在PyObject *PyDict_New(void)中,调用了宏定义EMPTY_TO_MINSIZE
    
    #define INIT_NONZERO_DICT_SLOTS(mp) do {                                
        (mp)->ma_table = (mp)->ma_smalltable;                               
        (mp)->ma_mask = PyDict_MINSIZE - 1;                                 
        } while(0)
    
    #define EMPTY_TO_MINSIZE(mp) do {                                       
        memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable));        
        (mp)->ma_used = (mp)->ma_fill = 0;                                  
        INIT_NONZERO_DICT_SLOTS(mp);                                        
        } while(0)
    	
    可以看出ma_table开始是指向ma_smalltable的,这和代码的注释一致
    
    mp->ma_lookup = lookdict_unicode; 给函数指针赋值,dict的搜索函数
    
    随着int PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value)的不断调用
    该函数会在最后判断
        if (!(mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2))
            return 0;
        return dictresize(mp, (mp->ma_used > 50000 ? 2 : 4) * mp->ma_used);
    可见在ma_fill = 6 && ma_mask=7 的时候,走到了dictresize
    会重新申请新的内存, ma_table就不再指向ma_smalltable, 而是新的内存,
    然后把原来老的内容拷贝到新的内存里面.by calling insertdict_clean
    之后 ma_fill = ma_used = 6, ma_mask = 31
    
        /* Get space for a new table. */
        oldtable = mp->ma_table;
        assert(oldtable != NULL);
        is_oldtable_malloced = oldtable != mp->ma_smalltable;
    	    if (is_oldtable_malloced)
            PyMem_DEL(oldtable);
    		
    最后看老的内存是否应该释放
    如果老的是ma_smalltable, 就不管了


  • 相关阅读:
    P1128 [HNOI2001]求正整数
    zabbix-server端监控MySQL服务
    对服务器磁盘、CPU、内存使用状态,设置163邮件告警
    JDK8 的FullGC 之 metaspace
    JDK8-废弃永久代(PermGen)迎来元空间(Metaspace)
    JVM的方法区和永久带是什么关系?
    如何使用start with connect by prior递归用法
    JVM原理讲解和调优
    jvm 性能调优工具之 jstat
    记一次HBase内存泄漏导致RegionServer挂掉问题
  • 原文地址:https://www.cnblogs.com/pangblog/p/3341846.html
Copyright © 2011-2022 走看看