4. 同步通信
  客户端和服务器之间的同步通信会带来时间的损耗,对于需要快速通信的系统来说,这会成为一个问题。Thompson说,它的解决方案并不是购买更加昂贵和快速的硬件,而是使用异步通信。在这种场景下,客户端可以发送多个请求到服务器端,而不必等待它们之间的响应。采用这种方式需要改变客户端发送请求的方式,但这是值得的。
  3. 文本编码
  开发人员很多时候会选择使用文本编码格式实现链路上的数据传输,比如JSON、XML或Base64,因为“这对人类是可读的”。但是Thompson指出在两个系统之间进行对话的时候,是没有人读这些数据的。借助这种方式,使用简单的文本编辑器能很容易地进行调试,但是在将二进制数据与文本之间进行互相转换的时候,这会带来很高的CPU损耗。该问题的解决方案是使用能够理解二进制的更好的工具,Thompson提到了Wireshark。
  2. API设计
  按照Thompson的说法,有一些与性能相关的负面影响是由API引起的。它使用如下的代码来阐述较差的代码签名:
  public void startElement( String uri, String localName, String qName, Attributes atts) throws SAXException
  描述:
  在处理XML的时候,通常我们并不会使用这些值[三个String以及属性的集合]。我们分配了很多的内容,但是却将其浪费并抛弃掉了。这会损耗电池的寿命,白白地浪费资源。我们需要使其更加简单一些。
  他建议采用如下的签名,实现更加简单的方法:
  public void characters( char[] ch, int start, int length) throws SAXException
  有些人可能会抱怨后面的这个方法要比前一个更难用,Thompson建议采用组合的方式,将其中一个用另一个封装起来,这样的话,能够给用户多一个选择。如果性能不是什么问题的话,可以采用第一种(使用String),否则的话,第二个方案会更好一些。
  Thompson提到的第二个样例是字符串拆分:
  public String[] split(String regex)
  这个方法签名相关的性能问题包括:
  每次方法调用的时候,正则表达式都需要进行编译;
  需要实例化一个动态的结构,用来存储字符串中所包含的初始数量未知的token;
  返回的结构是一个固定大小的数组,这必须要将token收集到一个临时的结构中,然后再拷贝到数组里面;
  如果调用者想要对这些token进行一些操作的话,比如排序,需要将它们拷贝到另外一个结构之中。
  更好的方案是使用Iterable,它能够避免在内存中创建中间状态的token副本:
  public Iterable split(String regex)
  另外一种方案是允许调用者提供存储token的集合。如果调用者想要对token列表去重的话,应该传递一个Set进来,如果想得到有序列表的话,需要传递一个TreeMap进来:
  public void split( String regex, Collection dst)
  1.日志
  Thompson所列的的性能问题是写日志所耗费的时间。他通过一个图表展现了当线程数增加的时候,日志操作所耗费的平均时间:
  这个图显示了一个的顺序操作,不管使用多少线程来记录日志,所需的时间均呈线性增长。Thompson说大多数已有的日志系统都可以得出这样一幅图表,“Logger是系统中大的瓶颈之一”。这个问题的解决方案是使用异步的Logger。
  另外,Logger所记录的数据应该是结构化的数据,便于后续的工具进行读取和处理,而不应该是一堆String。如果是记录重复的错误,他建议在错误第一次出现的时候进行记录,后续出现时只需对一个计数器进行递增,告知对应的错误出现了多少次即可。对于实时系统的调试,Thompson建议使用代码编织(code weaver)的技术,如Byte Buddy,因为它能够避免编写和运行不必要的日志代码。