面试题流散汇总

1、n位数全排列 大字符串相加 SQL HTTPS 根据简历来问

2、MapReduce和Spark的主要区别在于,MapReduce使用持久存储,而Spark使用弹性分布式数据集(RDDS)。Spark之所以如此快速,原因在于它在内存中处理一切数据。没错,它还可以使用磁盘来处理未全部装入到内存中的数据。Spark已证明在数据多达PB的情况下也轻松自如。它被用于在数量只有十分之一的机器上,对100TB数据进行排序的速度比Hadoop MapReduce快3倍。

Spark与MapReduce是一种相互共生的关系。Hadoop提供了Spark所没有的功能特性,比如分布式文件系统,而Spark 为需要它的那些数据集提供了实时内存处理。完美的大数据场景正是设计人员当初预想的那样:让Hadoop和Spark在同一个团队里面协同运行。

3、Linux开发环境配置:putty、ssh、windows和linux共享用samba、mingw、codeblock、cygwin、lfs经验

4、python垃圾回收机制分析  

参考链接:https://blog.csdn.net/tab_space/article/category/5981645

经典的垃圾回收有几种,例如,引用计数回收器,标记清除回收器,重定位回收器,拷贝回收器及世代回收器等等。这里主要介绍引用计数,标记清除和世代三种,还有两种其实和世代回收器类似。

PyObject对象内存模型:

一个PyObject必须包含ob_refcntob_typeob_refcnt是这个对象的引用计数,而ob_type则是指向_typeobject结构体的指针,它是Python内部的一种特殊对象,它是用来制定一个对象类型的类型对象,所以上图中它指向了一个PyTypeObject

在PyTypeObject中定义了大量的函数指针,这些函数指针最终都会指向某个函数,或者指向NULL。这些函数指针可以视为类型对象中所定义的操作,而这些操作直接决定着一个对象在运行时所表现出的行为。

在Python中,对象机制的核心其实非常简单,一个是引用计数,一个是类型信息。

定长对象内存模型:

在Python中,List其实是一个可变长的,类似于C++中的vector的数据结构,为什么它的内存模型是定长的呢?

其实它的内存模型的字段都是元数据(meta-data),而真正存放数组数据的是ob_item指向的一个数组。

ob_sizeallocated都和PyListObject对象的内存管理有关,PyListObject所采用的内存管理策略和C++中的vector采取内存管理策略是一样的。在每一次需要申请内存的时候, PyListObject总会申请一大块内存,这是申请的总内存的大小记录在allocated中,而实际被使用了的内存的数量则记录在了ob_size中。

变长对象内存模型:

标记清除方法遵循垃圾检测和垃圾回收两个阶段,其简要工程如下:

1). 寻找根集(root object set,所谓的根集即是一些全局引用和函数栈中的引用。这些引用所用的对象时不可被删除的,而这个根集也是垃圾检测动作的起点。

2). 从根集出发,沿着根集中的每一个引用,如果能到达某个对象A,则称A为可达对象,可达对象时不可被删除的。这个阶段就是垃圾检测的阶段。

3). 当垃圾检测阶段结束后,所有的对象分可达对(reachable object)象和不可达对象(unreachable object)两部分,所有的可达对象都必须予以保留,而所有的不可达对象所占用的内存将被回收,这就是垃圾回收阶段。

全集的数据结构为链表,每一个PyObject中在GC的时候,头部会添加一个叫做PyGC_Head的结构:

当generation 0的对象个数大于一定阈值时,就需要进行一次世代回收collect_generations。collect_generations函数中,Python会借第0代内存链表的越界触发了垃圾收集的机会。输入参数generation表示函数必须指定某一代,在这里我们称为”当代“;返回不可达对象的个数,回收过程描述为:

static Py_ssize_t
collect(int generation)
{
    //[1]: 初始化定义               m个可被回收,n个不可被回收

    //[2]: 将比当代处理的“代”更年轻的“代”的链表合并到当前“代”中

    //[3]: 将当代对象中的引用计数抄一份到对象的Py_GC_Head中(gc_refs = ob_refcnt)

    //[4]: 通过traverse机制更新对象中的引用计数,最终不可达对象的引用计数会被减为0,不为0即是root object

    //[5]: 初始化一个链表叫unreachable,把不可达的对象(引用计数为0)移到该链表中

    //[6]: 又初始化一个链表叫finalizers, 把链表unreachable中带有__del__的对象进一步分离到finalizers

    //[7]: 将finalizers中的对象又设置为可达对象(gc_refs=GC_REACHABLE)

    //[8]: debug信息,可以打印可回收对象

    //[9]: 通知所有弱引用到unreachable对象的对象,如果弱引用对象仍然生存则放回

    //[10]: 删除unreachable链表中的对象(垃圾),这会打破对象的循环引用

    //[11]: debug信息,可以打印不可回收对象

    //[12]: 把所有finalizers链表中的对象放到gc.garbage中

    //[13]: 返回不可达对象个数
}

 

猜你喜欢

转载自blog.csdn.net/chenkaifang/article/details/81255396
今日推荐