追根溯源-编程语言&性能优化
- Posted by 微博@Yangsc_o
- 原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0
摘要
昨天晚上莫名其妙的头脑风暴,凌晨4点多才睡着,脑子一直充斥这些语言:c、c++、java、python、js、php,线程、进程、网络IO、性能等等;
重新探究事物的原理能帮助各种实践遇到的各种疑问,这大概就理论指导实践;
今天就来简单聊一聊,后续再写博客展开详细叙述。
语言分类
- 汇编:MASM
- 编译:c、c++、oc
- 混合语言(半编译&半解释):java、C#
- 解释语言:python、ruby、perl
- 脚本语言:js、php、asp
- 静态语言:c、c++
- 半动态语言:java
- 动态语言:python、js、php、c#
- CPU运行模式:
- ring0:内核态(内核函数)
- ring1:
- ring2:
- ring3:用户态(非内核函数)
ring0是指CPU的运行级别,ring0是最高级别,ring1次之,ring2更次之……
也就是,如果一个语言想要提供性能
- 向上优化:通过编译器,编译为静态;
- 向上选择:有利于编译器向上优化;有利于静态化、尽量多的运行在内核态;eg:java的JIT编译器会将运行频率很高的字节码直接编译为机器指令执行以提高性能;
多进程和多线程
为了提高程序的性能,我们一般都会采用多进程或者多线程的技术,有必要对比一下进程和线程;
- 系统资源:进程>线程
- 稳定性:进程>线程
- 数据同步:线程(线程切换)>进程(进程通信)
- 调用难度:进程>线程
通信机制
- 信号(Signal):信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生;
- 管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系(父子进程)的进程间使用
- 命名管道(FIFO):有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
- 消息队列(Message Queue):消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。
- 共享内存(Shared Memory):共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。如信号量,配合使用,来实现进程间的同步和通信。
- 信号量(Semaphore):信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
- 套接字(socket,基于IP):套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同主机间的进程通信。
- unix域套接字(socket,不基于IP):只需要在一台机器上的两个不同进程间通信,还要用到IP地址就有点大材小用了。
锁和原子性
- 互斥锁(Mutex):见名知意;
- 读写锁(wrlock):读不加锁,写加锁;
- 自选锁(spinlock):while(ture),原地打转;
- 原子操作:最小运行单元;操作容器(atomic)
说到这个地方免不了提一下 volatile:c++、java都有这个关键字;
- 知识点1: 内存屏障,c++中volatile修饰变量可以防止编译优化;java中叫做指令重排,都是一个意思;
- 知识点2: 线程可见:就是声明为随时可能发生变化,易变声明;使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据;
- 可重入锁(ReentrantLock):应用级别的锁
资源
寄存器、堆、栈、全局区、常量区
性能:寄存器>栈>堆
- 寄存器:CPU操作;
- 栈:内存
- 堆:内存(用户分配)
空间换时间
- 内存缓存:内部、外部缓存;
LRU(least recently used): 如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。
LFU(Least Frequently Used):最近最少使用算法。它是基于“如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小”的思路。LFU有更精确的统计;
FIFO: 在FIFO Cache设计中,核心原则就是:如果一个数据最先进入缓存中,则应该最早淘汰掉。也就是说,当缓存满的时候,应当把最先进入缓存的数据给淘汰掉。在FIFO Cache中应该支持以下操作;
- 运算(操作)静态化:查表、映射;
- 中间结果缓存或者预处理
池化技术
- 内存池
静态、动态(非固定长度)
- 线程池
静态、动态(多用于无状态的web服务)
- 连接池
数据库、redis等连接池
数据结构
- 数组和连续内存
高效:索引、size、遍历、复制
低效:插入、扩容、查找
- 链表和双线链表
高效:端插入、遍历、扩容
低效:size、查找
- 红黑树(java treeMap)
高效:排序、找上线最近元素、查找、遍历、扩容
低效:插入、删除
- size效率和实现有关系
- 哈希
高效:海量数据插入、删除、查找
低效:排序、size
- 堆:大顶堆、小顶堆
高效:取最大N个元素
性能分级
- 轻CPU(逻辑运算) > 重CPU(查找运算) > 内存交换(copy) > IO(文件、DB、网络IO:TCP/UDP)
- 由于IO操作实在性能低效率:于是有了IO多路复用技术;
参考
你的鼓励也是我创作的动力