认真学完计算机体系结构,操作系统,数据结构,算法之后,我究竟得到了什么-

Posted by AlstonWilliams on February 17, 2019

套路都这么说,更加理解了计算机体系结构,操作系统,数据结构,算法.

然而,今天我们不搞这些八股文.我们来谈一下,究竟得到了什么.

无论各位看没看过玄幻类小说,都知道其中的修道者,需要经过一次次的历练,然后渡劫,上升到更高的境界.

之前虽然也会用不少框架,但是终究是不能知其所以然.这种境界,就是人们常说的码农.

而虽然早就想到了飞升的方法,却并没有飞升.为何?因为不知道需要什么样的条件,不知道应该怎样渡劫.

而认真学完这些之后,可算是具有了渡劫的条件,也了解了如何来渡劫.

其实,每次渡劫需要的条件,都是那些理论知识.现在我了解了这些知识,渡完了这次劫.下次要想渡分布式的劫,就需要了解分布式系统的理论知识.

说实话,之前做东西,都是做到能使用就行了,即使想要进行性能调优,也一直苦于无处下手.

学完计算机体系结构和操作系统之后,更深入的了解了线程和信号量等内容之后,我开始有意识的考虑写的程序是不是线程安全的,会不会因为高并发而出现不可预期的错误.

学习了JVM之后,我了解了如何在JVM层面进行调优,以及分析出现错误的原因.比如说,昨天的文章的末尾,我们说到,我们还可以采用Hibernate缓存或者Redis缓存来进一步提升性能,但是,如果让我们选择的话,我们会采取Redis缓存.因为Hibernate缓存应该是在内存中存储一个跟Hash表一样的东西,其中查询语句是这张表的Key,而Value是以前Hibernate查询的结果.这样的话,Hibernate一直维护这张表,GC就不能回收它.如果这张表很大的话,就会消耗相当大的一部分内存.我昨天计算了一下,存储一千个我们项目中的对象后,至少需要330M内存.我们的这个对象的大小的计算,还是没有经过对齐所计算出来的大小.在考虑到对齐,以及方法等需要的内存,计算出来的值,比上面的值还要大很多.所以,Hibernate缓存虽然确实减少了建立JDBC Connection以及执行操作的花销,但是,数据量一多,就会占用大量的内存,因为还被引用,又不能被回收.而如果采用Redis缓存的话,我们将查询的结果,序列化成JSON字符串之后,存到Redis,下次需要的时候,就直接根据Key,从Redis中取出来数据,这样就不用担心内存的问题了,只需要考虑带宽的问题,以及过期数据的处理问题.我们还可以在再项目中增加一个本地缓存,如Java中的EhCache,实现热点数据存到本地缓存,其他数据缓存到Redis.这样可以进一步提高性能.因为一般情况下,都是热点数据访问的比较多.所以,Redis的方案,对比Hibernate缓存的方案,是更为好用的.

学习了数据结构之后,特别是树,现在要自己设计一个需要的数据结构的时候,就显的游刃有余了.了解了每种结构的特点,在需要一种数据结构的时候,我们就能快速的反应出到底什么样的数据结构合适.而如果用了错误的合适结构,会造成操作起来以及理解起来都有困难.比如说,我们要保存到来的消息,然后按其到来的先后顺序来消费,我们采取什么样的数据结构比较好?当然是队列.这就是消息队列的采用的数据结构.如果我们采用数组,我们需要为其限定长度.大了浪费空间,小了又不够用.如果小了,前面的消息没有处理完,又来了新的消息的话,我们该怎么办?为数组调整长度,本身就是很不方便的.甚至是不可能的.而如果采用队列的结构,因为队列会自动伸缩,我们就没有尺寸的问题了.可见,采用的合适的数据结构,真是事半功倍.

学习完算法之后,开始有意识的衡量自己写的代码的算法复杂度了.比如说,写的一个根据Hibernate查询出来的数据构建出一棵树并递归的生成一个JSON字符串,方便我们保存到Redis的工具类,写完之后,分析了一下算法的时间复杂度和空间复杂度,发现每次都从全部查询结果中来匹配模式,使得需要大量的时间来遍历.而实际上,那些我们已经匹配完的查询结果,下次再用新的模式匹配时,是不需要的.空间复杂度上,因为现在是把全部的数据全都取出来放在内存中,如果数据比较多的情况下,本身就对内存是一个比较大的消耗.而且,如果是分页查询的话,将全部数据都取出来,是没有必要的.一般来说,最多查询三四页.所以说,我们其实浪费了大量的空间.

而且,了解了现在常用的算法之后,比如说了解常用的排序算法,我们需要对元素进行排序时,就能根据我们的场景选择最优的算法.而我以前只理解冒泡排序!!!

同样,计算机体系结构,操作系统,数据结构,算法,在进行性能优化的时候也很重要,因为性能优化涉及到各个方面,计算机网络,编译原理,汇编也都有涉及到.如果不清楚这些知识,注定是举步维艰.