Beautiful Code — go sort sort: optimize average calculation in symMerge and doPivot. Change code of the form `i + (j-i)/2` to `int(uint(i+j) >> 1)`. The optimized average calculation uses fewer instructions to calculate the average without overflowing at the addition. Analogous to https://golang.org/cl/36332. name old time/op new time/op delta StableString1K-4 49.6µs ± 3% 49.1µs…
ARC Cache算法
ARC(Adaptive Replacement Cache)是一种适应性Cache算法, 它结合了LRU与LFU。 LRU(Least recently used) 其核心思想是:假设刚visit的item,很有可能在未来被revisit 丢弃最近最少访问的items 通常用双链表实现 tips: redis并没有这样做,因为这样每个key至少会多出两个指针。 redis采用的是一种近似LRU,基本思想是随机取出一些key,形成一个小的POOL,然后在pool中采用LRU策略(相关源码:redis/src/evict.c) 缺点:忽略了frequency, 不适合大规模扫描等情况 LRU有一系列变种,比如LRU2, 2Q, LIRS等。 LFU(Least-frequently used) 其核心思想是:假设visit次数越多的item,很有可能在未来被revisit 适应大规模扫描 对热点友好 缺点:忽略了recency, 可能会积累不再使用的数据 tips: redis4.0开始支持了LFU,例如volatile-lfu, allkeys-lfu配置选项 ARC 整个Cache分成两部分,起始LRU和LFU各占一半,后续会动态适应调整partion的位置(记为p) 除此,LRU和LFU各自有一个ghost list(因此,一共4个list) 每次,被淘汰的item放到对应的ghost list中(ghost list只存key), 例如:如果被evicted的item来自LRU的部分, 则该item对应的key会被放入LRU对应的ghost list 第一次cache miss, 则会放入LRU 如果cache hit, 如果LFU中没有,则放入LFU 如果cache miss, 但在ghost list中命中,这说明对应的cache如果再大一丁点儿就好了: 如果存在于LRU ghost list, 则p=p+1;否则存在于LFU ghost list, p=p-1….
C++线程安全分析
C++线程安全分析 除了通过code review或者test来检测线程安全,有没有其它更好的办法? 答案是存在的,通过clang即可以进行这种检测,编译器对存在的线程安全问题会给出警告。 这种分析方法由Google开发,已经被Google大规模应用,参考 https://static.googleusercontent.com/media/research.google.com/zh-CN//pubs/archive/42958.pdf 示例example.cpp: 通过然后指定-Wthread-safety编译选项,即clang -c -Wthread-safety example.cpp命令编译即可以给出警告。 更多细节可以参考: https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
Supporting IPv6 DNS64/NAT64 Networks
从6月1日起,苹果审核要求支持IPv6 DNS64/NAT64网络了。 我们服务器和客户端都是Socket编程,IPv4地址。最后参照https://developer.apple.com/library/mac/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/UnderstandingandPreparingfortheIPv6Transition/UnderstandingandPreparingfortheIPv6Transition.html#//apple_ref/doc/uid/TP40010220-CH213-SW1,在客户端处理下即可。 需要说明的是, 在上述文档Apple给出的Listing 10-1 Using getaddrinfo to resolve an IPv4 address literal中,error = getaddrinfo(ipv4_str, “http”, &hints, &res0); 经测试,在IOS下,第一个参数为IPv4地址的情况下,第二个参数为http,ftp等常用字符串,服务器此时监听端口需改为协议默认端口才可能;或者第一个参数为域名,第二个参数为数字端口; 不支持第一个参数为IPv4地址,第二个参数为数字端口。坑爹。有两种方法解决这个问题 : 1) 域名+数字端口。 2) 先getaddrinfo, 再获取sockaddr_in或者sockaddr_in6,设置sin_port或sin6_port。 关于IPv6,可以参考下几篇文章: https://tools.ietf.org/html/rfc4038 https://github.com/WeMobileDev/article/blob/master/IPv6%20socket编程.md
深入了解死锁
死锁通常是因为获取锁时形成了环路。 死锁发生前 尽量不要使用共享 例如使用消息通讯,例如Erlang里的变量不变 尽量使用并发组件 例如java.util.concurrent 尽量使用非递归锁(不可重入锁) 例如pthread_mutex_t默认非递归 控制顺序 thread 1: Lock(a), Lock(b) thread 2: Lock(b), Lock(a) 转变为统一的顺序如Lock(a), Lock(b) 运行期警告 把Lock(历史)形成一个graph,看是否存在回路 超时机制 如带有timeout的wait, innodb_lock_wait_timeout等 工具测试 例如Intel inspector, Valgrind-Helgrind(pthread)等 PS. 银行家算法 由Edsger Dijkstra爷爷为设计THE操作系统创建,其使用场景也有些局限性,比如需要知道进程请求资源的可能数量,以及假设进程数量是固定的等,因此基本不具有实用性。 死锁发生后 堆栈查看 pstack(其实就是gdb thread apply all bt) jstack, jconsole ps. CPU100%也可以通过这种方法 检测机制 例如innodb的wait-for graph,形成环路(或者层次太深时也会认为死锁)时,此时会选择Undo量小的事务进行回滚。