不知不觉,一月份就已经过去了。想想似乎这一个月,并没有做什么事情。
这一个月,读了几本书。
通读了一遍《Programming Scala》。因为Scala就是基于Java的,所以还算比较顺利。不过,就在我写这篇总结的时候,回头翻看这本书的目录,发现好多内容都没有印象了。当时也没有做笔记。幸运的是,毕竟只是一门编程语言,二月份开始,要用Scala写Spark,可以巩固一下对Scala的理解。
通读了一遍《Programming Hive》。但是发现书中主要介绍的就是跟SQL相关的部分,只有自定义函数部分比较新鲜,于是就没有仔细阅读了,只是大体看了一下这部分,留下了一个印象,日后用的时候,能够知道参考哪部分资料。
阅读了《Kafka: The Definitive Guide》。这个月,由于家里有事情,回家了一个星期。这一个星期,忙完了之后,没有什么事情可以做,就开始了这本书的阅读。这本书,主要是精读了前半部分,后半部分关于性能调优,部署等的内容就没有细看。
目前为止,看过三本The Definitive Guide系列的书,《Hadoop: The Definitive Guide》,《HBase: The Definitive Guide》以及这本《Kafka: The Definitive Guide》。这个系列的书确实挺不错,从一些基础的内容,比如客户端的使用,到一些比较深入的内容都有介绍。书中都会介绍这个项目的架构,如何进行优化等方面的内容。
项目的架构,有论文的参考论文,可以理解的更加透彻。而优化方面的内容,实际上并不是很详细,只能说给一个大体的方向,具体的优化方法,还得根据实际的应用场景进行选择。
除了技术方面的书籍,还阅读一些其他方面的书籍。
先是阅读完了《史蒂夫乔布斯传》,从书中可以了解到Apple公司的兴衰。书中的视角还算比较公正,对乔布斯的缺陷,没有偏袒。
后来打算培养一下自己的艺术气息,就读了一部分《艺术的故事》。后来发现,似乎对艺术的感觉并不是那么强烈。
于是就阅读其他的书籍,开始阅读《未来简史》,阅读了三分之一左右,确实是蛮不错的书籍,能够引发对人类的本质的思考。
后来,在搜索书籍的时候,偶然发现了一本叫做《编程大师访谈录》的书籍,目前正在读这本书。这本书以对话的方式,记录了一些大牛对编程的思索,以及其编程的习惯方式等。这本书的出版时间比较早,所以书中很多大牛的预测,在今天早已经实现了。这本书目前也读了三分之一。从书中可以看到,所有大牛在当时都预测个人计算机将会非常普及。在当时大型机当道,出现的少量小型机也只有程序员这一个用户群体,这样一个时代,他们就有如此先见。今天,我们验证了他们的预言。
在读完这本书之后,再接着阅读《未来简史》。不过我估计二月份能够读完这两本书就不错了,因为时间不太多。
除了阅读了一些书籍,还阅读了一篇论文,《Bigtable: A distributed storage system for structured data》。由于之前已经通过《HBase: The Definitive Guide》这本书有了一个大体的了解,所以,阅读起来还算是比较轻松。阅读完论文就可以发现,HBase是严格按照这个论文来实现的。
除此之外,还阅读了Hadoop中关于MapReduce以及YARN的源码。对一个Job是如何Run,ResourceManager以及NodeManager是如何处理的,有了一个比较清晰的认识。但是,由于阅读的时间其实并不长,当前只是注重于处理的流程,对一些比较重要的内容并没有深入了解。比如:
- YARN中,几种Scheduler的实现
- YARN中,几种实现Container的方式
- MapReduce中,Reducer阶段的几种merger的实现
- YARN在启动Container的时候,如何按照数据的存储位置来决定Container的位置,从而减少数据的传输
- ApplicationMaster如何确定接下来要运行MapTask还是ReduceTask
这一个月,我也一直在探索,如何去获取业界,以及学术界最新的进展。因为,之前看阿里的技术直播时,在介绍阿里内部实现的一个负载均衡器SLB(好像是这个名字)的时候,主讲人介绍说,由于是在TCP/IP协议栈的第四层进行的负载均衡,以及用到了很多硬件方面的新进展,所以,基本上这个负载均衡器的性能就是硬件的性能。具体是那些进展,我现在也记不起来了。只记得当时在看的时候,就非常苦恼,为什么我就没有地方获取这种最新的进展呢?
仔细想想,猛然发现,其实,我学习的东西,看到的东西,都已经是非常老,非常稳定的了。即使也会尝试一些业界出现的新技术,但是并不是这种底层的东西。不是底层的新的东西。而底层的进化,对于性能优化,有很大的帮助。
于是,我就一直在思索,也在探索,如何获取业界和学术界的最新的进展。
想到之前在哪看到过,某某算法,或者某某技术,它们的论文,是最先发表在IEEE,或者ACM上面的。于是,就想着,或许可以从这里入手。也去IEEE或者ACM的Transactions或者Journal上,查看最新的论文集,来获取学术界最新的进展。
后来,咨询老师,也获取到了另外一种途径。就是查看对应领域都有某些顶级会议,然后通过查看这些会议收录的论文集,来获取最新的进展。
遗憾的是,虽然找到了获取最新进展的方法,但是,由于目前是处于工业界中,并没有太多的时间,让我来仔细阅读这些论文。
而且,很多领域,似乎并没有顶级会议。我搜索了大数据方面以及分布式系统方面的顶级会议,但是,没有搜索到。而关于数据挖掘,人工智能的倒是很多。不过幸好IEEE中都有对应的Transactions.
阅读了上面的那些社科类,传记类的书籍之后,我也意识到,社交圈子对一个人的影响真的很大。
美国著名物理学家费曼先生,在大学以及研究生的期间,其导师也是当时世界著名的物理学家。
比尔盖茨虽然是中途辍学,但是,他就读的是,哈佛大学,他的父亲是国会议员,母亲是IBM董事会成员。所以他有机会跟IBM合作,结识各种优秀的人。
我羡慕甚至嫉妒那些在Standford,麻省理工大学等有着世界上著名CS专业,有着世界上最优秀的科学家,有着世界上最优秀的导师,在这些大学的学生。
这些学生,也走在了相关领域的最前沿。
我羡慕他们,因为他们可以少走很多弯路。他们可以获取到最新的知识,最权威的知识。他们可以学习到世界顶级科学家的工作方式,学习到很多我所学不到的东西。而我,自认为已经非常努力了,每天有效率地工作和学习接近十三个小时,却也只能在世界的CS学生中,处于中等位置。
我自认如果我也能获取到这些资源,必然不会比他们差,甚至会比他们更好。
但是我没有这些资源。所以我经常会提醒自己,你只是一个渣渣,你完全可以做的更好。
在阅读Hadoop的源码的时候,从网上看到的关于优化Hadoop的方法,我就在想,为什么要这么优化?他们怎么知道要这么优化的?我从哪里也可以学习到这些关于优化的方法?
就在今晚,我突然有点想明白了。
性能调优的目的,就是为了提高性能。
那么我们怎样提高性能?
- 让程序使用更少的内存
- 减少写磁盘的次数,或者往磁盘写的字节数,因为磁盘的速度跟内存的速度差了两个数量级
- 减少上下文切换的次数,以及内核态和用户态之间转换的次数
- 减少程序的步骤。每一个步骤,都是对性能的消耗。所以,能够用更少的步骤做出来,就尽量用更少的步骤
- 优化网络传输,比如,调节缓冲区大小,减少传输的字节数,选用合适的协议,UDP协议性能比TCP要好,因为它不存在三次握手这些额外的开销,但是它需要忍受一些包丢失的状况
- 阻塞和非阻塞
我认为,性能调优可以从三个方面进行:
- 针对业务进行调优
- 针对代码进行调优
- 针对操作系统,内核等调优
第一条,针对业务进行调优。之前在一个群里,讨论开源软件的问题。有一位朋友就说,开源软件,性能都很差,跟大公司内部实现的,性能方面根本没有可比性。
我认为这种说法其实是不正确的。我不知道他是如何得出性能方面没有可以性这一个结论的。但是,一款软件,不管是开源的还是大公司内部的,假设我们只是拿过来使用,而不清楚它到底是为了什么而设计的,适应于哪些应用场景。你应该如何调节它让它适应你的场景的话,那它的性能应该都不会达到最好的状态。在大数据的处理过程中,假设我们不考虑数据倾斜的情况,而只是瞎分区,那么,数据处理的效率必然不高,木桶效应嘛。在MapReduce中,Mapper会将结果进行排序,然后输出。假设我们有20MB的输出数据,而缓冲区只有10M,那必然就会导致往磁盘读写数据,性能必然会有损失。
所以,在使用一款开源软件的时候,我们至少应当先根据我们的业务场景,对它做一些调整。大公司内部实现的工具,未必就比这些好,只是他们充分考虑到了他们的需求,他们的业务场景,进行了针对性设计。而开源软件则是针对大众需求的。所以开源软件的性能,可能看起来比不上大公司内部的软件。
第二条,针对代码进行调优。就拿JVM举例,我们都知道,一般情况下,对象都是分配在堆内存上。一个对象在分配时,可能会导致Minor GC, Major GC。而且,一个对象在创建时,并不是简单的在堆内存上分配内存就可以了,还要对对象进行初始化。所以我们如果可以重用一个对象,而不是每次都重新new一个对象,既可以避免可能产生的GC,又能不必重新初始化,效率必然高一些。所以,现在有很多重用的技术,比如,数据库连接池,对象池,线程池,还有JVM复用等。在MapReduce中,JVM复用对于性能优化,有着不一样的意义。因为JVM的创建相对来说还是比较重量级的,而每个Container启动时都要创建一个JVM。另外,Hadoop中,也会根据数据所在的位置等信息,为Task分配Container,这样就能减少很多不必要的数据传输。这些都是在代码层面的优化。
代码层面的优化还有很多,比如,在阅读《Kafka: The Definitive Guide》时,作者提到了他们利用zero-copy来提高性能。zero-copy减少了数据传输的时候,用户态和内核态切换的次数,复制的次数更少,因此,能够提高性能。还有我们知道,NIO能够减少线程的使用,既然线程的使用少了,需要进行互斥,同步的可能性就小了,我们使用锁的几率就小了。而且,上下文切换的次数就少了。性能自然高一些。很多其他的小细节,对于性能,都有一些或多或少的影响。
第三条,针对操作系统,内核进行调优。比如,调整操作系统交换区的大小,尽量避免换页操作等,调节缓冲区的大小等。
如果能从这三个方面进行优化,我想,在使用这款开源软件的过程中,应该不会有什么性能问题。
就算开源软件有的地方在设计的时候确实不符合我们的业务,我们也是可以修改的嘛。
我们可以看到,这些优化的地方,其实都是跟操作系统密切相关的。我们必须理解操作系统的工作原理,如何读写数据,如何进行运算等,在优化的时候,才有理可依。
第三条那里,我写的很少。因为我也不清楚,针对操作系统,针对内核,针对硬件,如何进行优化。实际上,目前,我之前最多只是在代码层面进行过优化。对Linux操作系统,内核方面,硬件方面,不是很熟悉,自然也就没有机会进行优化。
而且,上面说的那些优化的点,在进行Web开发的时候,可能并没有什么。但是,如果我们要开发一款中间件,一款作为基石的产品,就必须要考虑这些因素了。
根据各种性能测试工具,发现性能瓶颈,进行针对性优化。
一月份总结完了,那么二月份,除了正常的工作,我要做什么呢?
- 深入阅读MapReduce和YARN的源码,理解上面我提到的几个方面
- 挖掘MapReduce和YARN可以进行性能优化的地方
- 修改Hadoop的源码,目前想到的有:
- 在Reducer阶段,可以根据Value进行排序
- 让Hadoop可以输入不同Job的结果到相同的目录,即如果Job的输出目录已经存在的话,也可以输出,并不会报错
- 总结MapReduce和YARN的源码,并写成文章发表出来
- 对Hadoop进行性能测试
- 阅读《Linux Performance and Tuning Guidelines》,加深对Linux的理解,增强对Linux进行性能调优的能力
- 阅读完《编程大师访谈录》