Performance

共 105 篇文章。

Buffer和cache的区别是什么?

• Development

buffer和cache是两个经常被混为一谈的概念。从直观上说,两者都具备改善系统 I/O 吞吐量的能力,但是这两个概念是有区别的,其提高系统I/O吞吐量的原因也不尽相同。

阅读全文… ( 本文约 811 字,阅读大致需要 2 分钟 )

客户端应该去计算什么?

• Development

这是一个很有意思的话题:随着计算机技术的发展,客户端的计算能力越来越强。想要提高在服务器端运行的系统的负载能力,最直接有效的办法就是把计算任务尽可能交给客户端去做,并减少两者之间的交互;然而,另一方面,这样做又可能会带来一些其他问题,例如,客户端完成某些计算任务的时候可能会比较慢(因为在客户端可以用到的资源比较少,想要保持兼容性最好的办法就是只使用普适的Java Script子集),或者,作为安全系统的一个最基本的原则,任何来自外界的数据都是不应被信任的,等等。

阅读全文… ( 本文约 999 字,阅读大致需要 2 分钟 )

ZFS性能的一些优化结论

• Data Management

最近几天测试了一下盘很多(具体说是24块盘,其中2块热备的JBOD)的时候ZFS的性能特点。一些结论

a) ZFS的随机读性能比较差(相对于顺序读写)。这一点除了改为用mirror而不是raidz1/z2之外似乎没什么太好的办法。同样多的硬盘做成两组raidz1(11+11+2),与做成两块盘一组的11组mirror的pool相比,针对同样的数据集的随机读性能相差可达10倍多,当然,mirror的结果是顺序写性能会差一些。作为副作用,mirror时的读性能可提高大约4倍左右。

阅读全文… ( 本文约 451 字,阅读大致需要 1 分钟 )

一部分应用层协议放进kernel?

• Kernel

先把想法记下来。

  • 提供一种描述语言,将应用层协议描述成DFA;
  • 一个generator将DFA转换为代码;
  • 用户态程序通过某种接口来向kernel请求已经协商好的该种协议的socket并由kernel直接填写一部分数据结构;
  • 应用程序对socket的第一个回应有时间限制—-如果一段时间之内不回应,则系统将该socket交给下一个监听进程。

解决的问题:

阅读全文… ( 本文约 277 字,阅读大致需要 1 分钟 )

改一行代码带来的性能改进

• Kernel

FreeBSD先前的vesa framebuffer驱动有个问题,就是滚屏的时候会比较慢。jkim大长辈于是改了一行代码。

好吧,我承认我之前一直以为是console驱动想要锁&Giant的问题。其实真正的原因是默认的pmap_mapdev并不做写合并,所以应该呼叫更低阶的pmap_mapdev_attr并传入PAT_WRITE_COMBINING参数。

阅读全文… ( 本文约 230 字,阅读大致需要 1 分钟 )

使用DSR模式实现单IP服务冗余

• Networking

FreeBSD支持以DSR(Direct Server Return,即服务器直接将流量通过路由器返回,而不经过负载平衡设备;俗称"单臂模式")模式提供服务。为了改善服务的可用性,可以使用这种方法来配置服务器。这种方法非常适合于大并发、大流量的环境。

阅读全文… ( 本文约 1278 字,阅读大致需要 3 分钟 )

垃圾收集里面用到的一种同步机制

• Kernel

先胡乱记一笔。

利用原子操作(CMPXCHG)来修改正扫描的栈帧上的返回地址,令其指向修正垃圾收集表的子程序。这样做的好处是避免了垃圾收集器在程序运行过程中为配合垃圾收集器运行而需要引入的额外开销(垃圾收集器通过扫描栈来了解应用程序目前知道的内存,并将其从准备释放的内存列表中删去,因此,垃圾收集器会希望在扫描栈的时候那个栈帧不发生变化,或者能够检测到这种变化,通常的做法是垃圾收集器提供一套机制来让正在运行的线程阻塞,而这种逐栈帧扫描并配合适当的返回指针修改的做法,则可以几乎完全不阻塞正在运行的线程,同时避免了在收集器不动作时的日常同步开销)。

参与评论

可伸缩性 Scalability

• Distributed Computing

关于Scalability这个词的中文译法,目前还没有一个非常确切的定论。一些文献中将其翻译为"可扩充性",而"扩充"指的主要是Scale up;而在一些实际的用法中,Scalability还包括Scale down,因此,“可伸缩性"也许是比较贴近原文意思的说法。

互联网应用的可扩充性体现在两个方面:其一,是能够对系统容量进行扩充,也就是说,这个系统各个组件能够提供的服务的量,能够在需要的时候予以扩充(特别是通过添加新的服务器等等)。其二,是这种扩充是有效率的扩充,即,增加硬件投入时,其投入与所产生的效果是接近甚至达到成比例增加的。通常说来,“可扩充"同时暗含的需求是用户的使用习惯尽可能保持不变。如果我们关注某一具体的计算节点,可扩充性还应体现于提高计算节点性能,例如增加其CPU数量或内存容量时,能够相应地改善系统的容量或响应时间,等等。

而另一方面,“可缩减性"主要指的则是说一套系统能够运行在尽可能少的软硬件环境之中。对于大型互联网公司而言,这一点可能并不重要,而对初创公司来说这一点则非常重要。

在设计互联网应用的时候,充分地考虑系统的可伸缩性,能够极大地减少日后的维护开销,并帮助决策者对于投资所能获得的回报进行更加精准的估计;另一方面,高可伸缩性的系统往往会具有更好的容灾能力,从而提供更好的用户体验。

与解决很多其他问题类似,改善可伸缩性最常用的方法就是分治法(Divide and Conquer)。分治属于大道理一类,在实践中,我们比较常用的分治策略包括:

  • 提高计算的可并行度。简单的计算,例如连续执行的加法,可以将中间结果的计算并行完成;而复杂一些的计算,例如搜索,也可以通过类似的方式分派到不同的单元中进行,并最终在另外的地方完成汇总。这种策略,比较适合于数据集中数据之间直接关联度不大、生成数据集比输入数据集小很多,并且汇总计算本身引起的开销较小的情形。
  • 增加能够完成同一类任务的计算/服务单元数。这类做法中,计算/服务单元仅仅完成某种将输入变换为输出的工作,并且,这类工作不太依赖于其与外界交互产生的状态,简而言之,对于输入数据,计算/服务单元能够自行完成一个环节的计算任务并给出输出。这种策略比较适合于存在,或可能成为瓶颈的位置。举例来说,对于读多写少的应用,通过适当增加cache环节(这些cache是全冗余的,也就是不同的机器之间可以完全地相互取代),就能够有效地提高其负载能力。
  • 消除单一故障点/瓶颈。如果一个系统中某些数据只存在一份,或某种计算只能在某一点上完成,那么这些环节就会成为单一故障点,或性能瓶颈。消除这类问题需要更巧妙的设计,简单地将数据复制到更多的机器上并不能够从根本上解决问题,因为在这种结构中"主"节点仍会成为瓶颈。有时,为了达到这个目的需要进行一些折衷设计,例如分段提交的方法,在容忍一部分竞态条件(race condition)的前提下避免另一些、不能容忍的竞态条件。这类做法往往会导致局部吞吐量受到负面影响,或使设计变得复杂。
阅读全文… ( 本文约 2100 字,阅读大致需要 5 分钟 )

memchr(3) rewrite

• Development

I have taken some time to rewrite memchr(3) to utilize similiar algorithm as my strlen(3) did. Two different formular, however, would have a roughly 1/3 difference.

Currently I have taken an approach that when memchr(3) is trying to match a pattern of 8-bit, then consider the string as 8-bit, which uses the first formular which is expected to have uniform O(n) time complexity by reducing unnecessary branches.

This approach, however, might be bogus since if you find 7-bit character within a 8-bit string, in that case, memchr(3) would perform poorly, if there are a lot of characters having their MSB as 1.

阅读全文… ( 本文约 114 字,阅读大致需要 1 分钟 )