日记式的个人胡扯,没有一句话保证正确,谢谢围观,欢迎指正。。 通用与专用,没有好坏 首先举两个极端的例子:深度学习应用十分重要,因此人们愿意专门为它花钱设计新型专用芯片和硬件架构,甚至可能为了它的性能,没准以后会重新写了一个叫”DnnOS”(我自己瞎编的名字)操作系统;而Jc写的helloworld.py程序无论在Linux, Windows 95还是Win 10上怎么折腾,都是打印一行hello, world,没有任何区别的。 哪个更好的问题没有绝对的答案,也许深度学习的新型硬件没有键盘鼠标和显示器,DnnOS也只要实现一套新型硬件的驱动,复杂程度远远小于Linux和Windows。但是Jc的helloworld.py无论运行在多么复杂的系统上,都无法到一个好的深度学习模型所带来的价值;反过来说,即使这套新型深度学习工具再牛逼,可能都无法运行Jc的helloworld.py程序。 所以,废话就是,当然是各有利弊。 什么应用需要专用系统, 首先当然是嵌入式设备,有些嵌入式设备并没有操作系统,有些有经过精简的操作系统。为实际应用量身定做的硬件和软件,对权衡性能和成本应该是最有利的! 另一种是,在我看来,是专用服务器,比如一台专门的数据库服务器,那么首先它的硬件选型是很重要的,比如存储设备要选高端的,显卡就不要了;它的操作系统的很多东西就用不上了,比如DBMS通常会关掉OS的文件缓存page cache,甚至不用OS的文件系统,来自己管理缓存和裸块设备,包括很多多余的硬件驱动都是不必要的。 什么应用需要通用系统 最易想到应该使用通用系统的例子,就是每个人的手机还有个人电脑了,由于每个人的爱好和工作习惯不同,它们的任务多种多样,资源利用的特点也各不相同。80年代的PC、00年代的手机,都是以计数器、画图、记事本功能齐全作为卖点,后来随着系统的发展,甚至会搞出应用商店这种来增加系统的功能,这时,工作负载就更不唯一。这样,在为每个用户量身定做系统不现实的情况下,只有系统更通用才会更满足消费者的多样需求(比如有人爱拍照,有人爱打王者荣耀)。 另一种,可能是云,也就是各种虚拟化和分布式技术。原因很简单,租用云服务的用户所需要的不只是一种服务(可能是云主机、云数据库或者云存储),更重要的是负载也是无法预测的。最典型的例子是云虚拟机,这时,一个“需要通用”的操作系统运行在云上,那么这个云更通用,比通用OS还要通用。比如,一个可以称为“云操作系统”的系统,要保证计算、存储、内存的可伸缩性,这时一般OS是不提供的,还要保证运行和数据可靠,这都是通用(通用虚拟机)之外的通用(伸缩性、可靠性)。 通用也是专用 讨论了什么时候应该通用和专用,及其原因之后,突然觉得:通用也是专用,因为不管是通用的还是专用的。因为专用的本来就是专用的;而通用的,开发它们多数都是 专用 来赚钱的,不管是手机还是云。

“写放大”(Write Amplification)在存储系统中是很常见的。但是,即使都是在存储系统中,“写放大”也有很多种,各种的写放大原理并不是很一样。下边根据自己的理解,进行了下总结,如有问题,恳请指正。 1. 读写单元较大导致的写放大 在文件系统中,读写单元固定,比如都是4K,这样,如果write函数写的数据小于4K,则要先把整块读入,再修改,再把新的4K整体写入(O_DIRECT情况除外)。这个过程可以称为 RMW (Read-Modify-Write),这就是File System的写放大问题。[1][2][5] (注意:Read-Modify-Write被更广泛地用在原子指令[3]和RAID[4]中。) 再如,在DBMS等应用层存储系统中,同样存在自己管理的读写单元,如MySQL的默认读写单元称为页,默认是16KB,所以一次读写只能以页的单位进行,这时,小于页的数据读写同样会带来整页的读写,进而造成了“写放大”,道理和文件系统是一样的。 2. RAID中的Read-Modify-Write造成的写放大 如前段所述,RAID中更新一个块,需要额外读原始块、校验块,额外写校验块,所以多了两个读,一个写,也称为Read-Modify-Write[4]。 这是由于校验块必须更新,且根据异或运算的可逆性,新校验块=新数据块^旧校验块^旧数据块。 3. SSD中闪存特性造成的写放大 在SSD中,一个block可以分为多个page,在读的时候,可以以page为单位,但是写的时候,只能以block为单位。因此写的单元比较大。在上层(比如文件系统)读写单元相同的情况下,同样是读写1个page的大小,读的话直接读就行,写的话却需要先把与要写page同一个block的数据全复制一遍,加上修改的page后,再一起写入block。写入的数据量远比实际的大,这就是SSD的写放大问题。 4. 存储系统一致性机制造成的同步写放大 在存储系统的很多层次中,都有保证系统crash consistency(一致性)的设计。因此,不管是应用层的存储系统(如DBMS、KV-store)、虚拟化层中的镜像管理、系统层的文件系统,甚至是硬件层的SSD FTL[7],都要通过强制同步各种元数据的写入顺序,或者利用redo log的思想,用journaling、log-structured或copy-on-write等策略保证元数据写入目的位置生效前先完整地生成日志,来保证系统崩溃或断电时,元数据之间是一致。但是,如果多层存储系统重叠,由于一致性机制导致同步次数增加就会层层放大。 比如,运行在x86虚拟机中的levelDB,其一次更新操作就会(1)最终导致levelDB写log文件和写数据两次同步写,这两次写就又会(2)导致2次的Guest文件系统log写和2次Guest文件系统数据写,一共4次同步写,这4次写又会导致(3)虚拟化镜像管理层的4 x N次写(N取决于镜像为保证元数据crash consistency的同步次数,若是qcow2格式,N可能有5次之多[6]),最后导致(4)Host文件系统的4 x N x 2 = 8 x N次同步写。当然这是一种比较极端的情况,但实际应用中也应该存在。 5. 基于LSM树的KV系统的Merge操作造成的写放大 levelDB等KV存储广泛采用了LSM树等结构进行存储组织,其特点就是靠上的level的数据会最终被merge sort到下层,由于多数level在磁盘文件中,这也就导致了同一KV数据的总写放大,放大的倍数就是大约是level的数目。和前边4中写放大不同的是,这种写放大并非写操作时马上就会发生写放大,而是写操作发生时会潜在的导致“未来会发生”写放大,所以这种写放大只会导致整体写代价提升,不会影响实时的延迟性能,只可能会影响磁盘带宽或者在SSD做存储设备时影响闪存耐久。FAST 16上有篇论文也专门分析了这种写放大。[8] [1] Why buffered writes are sometimes stalled, http://yoshinorimatsunobu.blogspot.com/2014/03/why-buffered-writes-are-sometimes.html [2] Block size and read-modify-write, https://www.spinics.net/lists/linux-xfs/msg14456.html [3] […]