前言
最近面试,不出意外的被面试官大佬吊打,所以记录一下。
语言特性
考察 Erlang 内置的数据类型以及其特点。
- 数字:“ 整数的大小有上限吗? ”没有,唯一限制就是物理内存的大小。
- 原子:“ 了解过 Erlang 的 GC 吗?原子会被垃圾回收吗? ”执行
erlang:garbage_collect/0
可以对当前进程进行垃圾回收操作。原子一旦被创建,它就不会被删除,但是原子的个数是有限的。 - 列表:
++
是对列表进行添加的操作符,需要操作两边均为列表类型。“ 一长一短的列表使用 ++ 拼接,你觉得是长的还是短的放在左边更好?为什么? ”把短的放在左边更好,因为++
操作在 Erlang 底层调用了 C 语言的 append 函数,这个 append 函数会复制拷贝左边的变量,所以将短列表插入到长列表会更好。 - 字符串:“ 你觉得字符串是列表吗? ”是,只不过表现形式不一样而已,例如字符串“hello”是列表[$h,$e,$l,$l,$o]的一个缩写。
- 映射:“ 你觉得列表和映射哪一个的操作效率更高? ”在查询上 maps 更好, 而在遍历上 lists 更好。对于频繁插入和查询的数据,maps 是最佳的选择,lists 则适用于需要遍历的数据。
- 位串:“ 你觉得 binary 长度在 32/64 字节时有什么不同吗? ”小于 64 字节的 binary 直接创建在进程堆上,称为 heap binary;大于 64 字节的 binary 将创建在 Erlang 虚拟机全局堆上,称为 refc binary,可被所有 Erlang 进程共享......
考察语言的优势以及原理。
- 热更新:是指在不停止系统的情况下对运行的代码进行替换,只有涉及到数据结构的重大改变才需要停止系统。Erlang 运行时会保存一份代码的两个版本,所有本地调用的函数地址都会指向程序运行时最初的那个版本,而所有外部调用的函数地址都会指向最新的版本。
在 Erlang Shell 中的内置函数c:c/1
的步骤基本分为三步:
其中,第一步判断是否文件或者目录;第二步尝试去编译文件中的代码(即把 A.erl 源文件编译为 A.beam 字节码文件);第三步执行code:purge/1
清除标记为旧版本的代码。如果一些旧代码仍然有进程在执行使用,在代码清除之前,这些进程将会被杀掉。然后再执行code:load_abs/2
加载代码路径 OutFile 下的模块 Module,这个函数的效果与code:load_file/1
一样。 - 排序:Erlang 的
lists:sort/1
函数使用了快速排序(Quicksort)算法来对列表进行排序,其时间复杂度为O(n log n),其中 n 为要排序的元素数量。快速排序算法的基本思想是选取一个比较元素,将列表中的元素分为小于和大于比较元素的两部分,然后递归地对这两部分进行排序,最终将整个列表排序完成。
进程与线程
- “ 你认为 Erlang 的进程与电脑的进程是同一种吗? ” Erlang 的进程并不是操作系统层面上的进程,也不是线程,而是 Erlang VM 里的概念,每个 Erlang 进程都有自己的调度器,它们被映射到操作系统线程上。
- “ Erlang 的节点、虚拟机、IP、进程之间有无关联?是怎么样的一种联系? ”Erlang 的节点、虚拟机、IP、进程之间有联系。Erlang 节点是一个 Erlang 系统的实例,它可以在同一台计算机上或不同的计算机上运行。每个 Erlang 节点都有一个唯一的名称,由一个原子和一个 IP 地址组成。Erlang 虚拟机是 Erlang 运行时环境的一部分,它负责管理进程和调度器。Erlang 进程是在 Erlang 虚拟机上运行的,每个进程都有自己的调度器,它们被映射到操作系统线程上。
- “ 你了解 Erlang 的 监督者 Supervisor 吗?可以说说其作用? ” Erlang 中的 Supervisor 是一种重要的进程类型,其主要作用是监视和管理其他进程。当其他进程出现错误或异常时,Supervisor 会自动重启它们,确保系统的可靠性和稳定性。
具体来说,Supervisor 会维护一个进程树,其中根进程是 Supervisor 本身,其他进程都是 Supervisor 的子进程。每个子进程都有一个唯一的名称和一个进程类型,可以是普通进程、Supervisor 或其他进程类型。当一个子进程崩溃或出现错误时,Supervisor 会根据子进程的重启策略来自动重启它。重启策略包括简单重启、暂停重启、一次性重启等。
hru5f1