那是一家创业公司的技术面,前面聊得还不错,面试官突然问了个常见问题:“能说说Python的内存管理吗?”
我心想这题我背过啊,马上回答:“Python有垃圾回收机制,主要靠引用计数,还有循环引用的情况用标记清除和分代回收来处理。”说完我还挺自信,觉得答得挺全面。
面试官没说话,拿起桌上的笔转了一圈,然后轻轻摇头。我心里咯噔一下,知道自己肯定漏了什么。
他慢慢放下笔,问:“你说的是垃圾回收,那内存池和对象分配策略这部分,你怎么理解的?”
我当时就愣住了。内存池这个词我好像见过,但具体怎么回事完全说不清楚。后来面试官看我真的不知道,就换了个方向问:“那你知道Python为了提升效率,给小对象做了哪些优化吗?”
我支支吾吾说不上来。面试官叹了口气,说:“小伙子,Python的内存管理不只是垃圾回收,垃圾回收只是内存管理的最后一道防线。你回去多看看内存池和对象分配那一块。”
这道题没答好,后面自然就凉了。回去之后我翻了不少资料,才明白自己错在哪。
原来Python为了减少频繁向操作系统申请内存的系统调用,自己维护了一个叫内存池的东西。小对象(256字节以下)都会从内存池里分配,根本不会直接跟操作系统打交道。垃圾回收只是在对象不再被引用时,把内存还给内存池,而不是还给系统。
更关键的是,Python还分了几个等级:arena、pool、block。每个block大小固定,pool管理block,arena管理pool。这种分层设计让内存分配和释放都很快,不需要每次都去系统那里“麻烦”一下。
另外还有一个细节,引用计数机制本身也要靠内存池来管理。每个对象头部的两个指针(ob_refcnt和ob_type)都记录在固定位置上,这才让引用计数更新得那么快。
面试官摇头不是因为我答错了,而是因为我把垃圾回收当成了内存管理的全部。就像别人问你怎么管理家庭开支,你只回答“我们家的垃圾每天按时丢掉”一样,完全答偏了。
后来我再面试Python岗位,遇到同样的问题,我会这样说:“Python的内存管理分几层。第一层是对象层面的引用计数和垃圾回收,第二层是内存池的管理,包括arena、pool、block三级结构,第三层才是跟操作系统交互的大对象分配和底层内存复用策略。”这么说,面试官基本都点头。
所以如果你也没答到点上,别怪面试官摇头。面试时多想想问题的广度,别只揪住自己最熟悉的那一小块使劲讲。