线、进程切换
进程切换与线程切换的一个最主要区别就在于进程切换涉及到虚拟地址空间的切换而线程切换则不会。因为每个进程都有自己的虚拟地址空间,而线程是共享所在进程的虚拟地址空间的,因此同一个进程中的线程进行线程切换时不涉及虚拟地址空间的转换。
举一个不太恰当的例子,线程切换就好比你从主卧走到次卧,反正主卧和次卧都在同一个房子中(虚拟地址空间),因此你无需换鞋子、换衣服等等。但是进程切换就不一样了,进程切换就好比从你家到别人家,这是两个不同的房子(不同的虚拟地址空间),出发时要换好衣服、鞋子等等,到别人家后还要再换鞋子等等。
因此我们可以形象的认为线程是处在同一个屋檐下的,这里的屋檐就是虚拟地址空间,因此线程间切换无需虚拟地址空间的切换;而进程则不同,两个不同进程位于不同的屋檐下,即进程位于不同的虚拟地址空间,因此进程切换涉及到虚拟地址空间的切换,这也是为什么进程切换要比线程切换慢的原因。
现在我们已经知道了进程都有自己的虚拟地址空间,把虚拟地址转化为物理地址需要查找页表,页表查找是一个很慢的过程,因此通常使用Cache来缓存常用的地址映射,这样可以加速页表查找,这个Cache就是TLB,Translation Lookaside Buffer,我们不需要关心这个名字,只需要知道TLB本质上就是一个cache,是用来加速页表查找的。由于每个进程都有自己的虚拟地址空间,那么显然每个进程都有自己的页表,那么当进程切换后页表也要进行切换,页表切换后TLB就失效了,cache失效导致命中率降低,那么虚拟地址转换为物理地址就会变慢,表现出来的就是程序运行会变慢,而线程切换不会导致TLB失效,因为线程无需切换地址空间,因此我们通常说线程切换比进程切换快,原因就在这里。
引用地址:https://www.cnblogs.com/MrLiuZF/p/15190499.html
redis数据结构
String:在Redis中String是可以修改的,称为动态字符串(Simple Dynamic String 简称 SDS),说是字符串但它的内部结构更像是一个 ArrayList,内部维护着一个字节数组,并且在其内部预分配了一定的空间,以减少内存的频繁分配。
-
当字符串的长度小于 1MB时,每次扩容都是加倍现有的空间。
-
如果字符串长度超过 1MB时,每次扩容时只会扩展 1MB 的空间。
这样既保证了内存空间够用,还不至于造成内存的浪费,字符串最大长度为 512MB.。
List:双向链表 / 压缩链表(元素个数小于512个,每个元素的值小于64字节)
Hash:Hash用来存储一组数据对,每个数据对又包含键和值两部分。Hash也有两种实现方式:压缩列表和哈希表。
SortSet:跳表和压缩列表。
Set:有两种实现方式:有序数组和哈希表。
跳表:跳表是在链表的基础上,增加了多级索引,通过在多级索引上跳来跳去,来加快查找速度。
DNS解析
首先会搜索浏览器自身的DNS缓存–>系统自身的DNS服务器–>顶级域名服务器–>域名提供商
查询方式分两种,递归查询(按照查询过程一层一层的返回)和迭代查询(查询后直接返回)