<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.7.3">Jekyll</generator><link href="http://iamyb.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="http://iamyb.github.io/" rel="alternate" type="text/html" /><updated>2018-06-26T06:48:35+00:00</updated><id>http://iamyb.github.io/</id><title type="html">疯道扬飚</title><subtitle>Build a Jekyll blog in minutes, without touching the command line.</subtitle><entry><title type="html">Linux系统性能剖析工具（四）</title><link href="http://iamyb.github.io/2016/07/30/Linux-Performance-Utils-4" rel="alternate" type="text/html" title="Linux系统性能剖析工具（四）" /><published>2016-07-30T00:00:00+00:00</published><updated>2016-07-30T00:00:00+00:00</updated><id>http://iamyb.github.io/2016/07/30/Linux-Performance-Utils-4</id><content type="html" xml:base="http://iamyb.github.io/2016/07/30/Linux-Performance-Utils-4">&lt;p&gt;前面&lt;a href=&quot;http://yangbiao.info/2016/07/20/Linux-Performance-Utils-1&quot;&gt;（一）&lt;/a&gt;、&lt;a href=&quot;http://yangbiao.info/2016/07/27/Linux-Performance-Utils-2&quot;&gt;（二）&lt;/a&gt;、&lt;a href=&quot;http://yangbiao.info/2016/07/29/Linux-Performance-Utils-3&quot;&gt;（三）&lt;/a&gt;分别介绍了如何剖析系统CPU、内存、磁盘等性能的工具，主要关注点在单个计算机内部；而在接下来的这篇文章中，会将我们的视野伸向更加广阔的互联网络，介绍一些剖析网络性能相关的工具，包括ping，netstat，tcpdump，iftop，nethogs等。&lt;/p&gt;

&lt;h3 id=&quot;ping&quot;&gt;ping&lt;/h3&gt;

&lt;p&gt;ping是一个测试网络可达与否的工具，同时也可测量当前主机到对端主机的RTT (Round-Trip Time)。下面是ping本地localhost的输出：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ ping -c 5 localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.061 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.045 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.061 ms
64 bytes from localhost (127.0.0.1): icmp_seq=4 ttl=64 time=0.048 ms
64 bytes from localhost (127.0.0.1): icmp_seq=5 ttl=64 time=0.052 ms

--- localhost ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3998ms
rtt min/avg/max/mdev = 0.045/0.053/0.061/0.009 ms
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上面输出第一列是ping包的大小，ping包大小也可以通过-s选项指定；最后一列是该包RTT的时间。输出的最后一行包含了RTT的最小、平均、最大的时间。以下是ping命令的几个常规用法：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// -s ping localhost with max packet size
ping -s 65507 localhost  

//-c, count
ping -c 5 localhost  

// -f, flood ping with max packet size
ping -f -s 65507 localhost 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;netstat&quot;&gt;netstat&lt;/h3&gt;
&lt;p&gt;netstat可以查看系统当前所有网络连接的状态、路由表及性能相关的统计，比如可以用netstat -ts显示系统tcp连接的统计信息。可用watch命令配合netstat，检查系统tcp的收发状态：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ watch -d netstat -ts
IcmpMsg:
    InType0: 271693614
    InType3: 88
    InType8: 271656227
    InType11: 21
    OutType0: 271656227
    OutType3: 124
    OutType8: 271693627
Tcp:
    63 active connections openings
    8 passive connection openings
    58 failed connection attempts
    0 connection resets received
    4 connections established
    19130904 segments received
    19087366 segments send out
    22 segments retransmited
    0 bad segments received.
    58 resets sent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;从上面的输出中可以看到，系统tcp连接，收发的报文段数目等信息。对于udp协议来说，可以用netstat -us命令来查看。以下是netstat命令的一些其他常规用法：
	//dispaly interface
	netstat -i&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;//display all tcp connections state 
netstat -ta

//dispaly all udp connections state
netstat -ua

//dispaly the pid and program of udp connection 
sudo netstat -nlpu

//dispaly the pid and program of tcp connection 
sudo netstat -nlpu

//dispaly user related information with -e 
sudo netstat -te
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;tcpdump&quot;&gt;tcpdump&lt;/h3&gt;

&lt;p&gt;先用一个简单的例子，说明tcpdump的作用。案例的场景是这样的：有两台主机，在尾号147的主机上ping另外一台尾号为156的主机，然后在156主机上执行下面命令，如下：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ tcpdump -n -i eth0 icmp
01:49:09.311201 IP 10.141.115.147 &amp;gt; 10.140.163.156: ICMP echo request, id 1, seq 38336, length 64
01:49:09.311250 IP 10.140.163.156 &amp;gt; 10.141.115.147: ICMP echo reply, id 1, seq 38336, length 64
01:49:10.282256 IP 10.141.115.147 &amp;gt; 10.140.163.156: ICMP echo request, id 1, seq 38337, length 64
01:49:10.282303 IP 10.140.163.156 &amp;gt; 10.141.115.147: ICMP echo reply, id 1, seq 38337, length 64
01:49:11.283242 IP 10.141.115.147 &amp;gt; 10.140.163.156: ICMP echo request, id 1, seq 38338, length 64
01:49:11.283291 IP 10.140.163.156 &amp;gt; 10.141.115.147: ICMP echo reply, id 1, seq 38338, length 64
01:49:12.285230 IP 10.141.115.147 &amp;gt; 10.140.163.156: ICMP echo request, id 1, seq 38339, length 64
01:49:12.285268 IP 10.140.163.156 &amp;gt; 10.141.115.147: ICMP echo reply, id 1, seq 38339, length 64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;可以看到输出中都是ICMP echo的请求和恢复的包，这是因为指定了icmp选项把其他的数据包都过滤了。&lt;/p&gt;

&lt;p&gt;再来看一个例子。对先前主机147端的ping命令加上“-p”选项，可以把ping包的内容都填充为0xff，请求端的命令是这样的：“ping -p ff 10.140.163.156”；然后在接收端156的主机上，执行命令“tcpdump -n -X -i eth0 icmp”:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubtunu$ sudo tcpdump -nX -i eth0 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
02:08:45.515524 IP 10.141.115.147 &amp;gt; 10.140.163.156: ICMP echo request, id 1, seq 39510, length 64
        0x0000:  4500 0054 7d3a 4000 3801 9926 0a8d 7393  E..T}:@.8..&amp;amp;..s.
        0x0010:  0a8c a39c 0800 3125 0001 9a56 b6b1 9d57  ......1%...V...W
        0x0020:  0000 0000 d779 0100 0000 0000 ffff ffff  .....y..........
        0x0030:  ffff ffff ffff ffff ffff ffff ffff ffff  ................
        0x0040:  ffff ffff ffff ffff ffff ffff ffff ffff  ................
        0x0050:  ffff ffff                                ....
02:08:45.515559 IP 10.140.163.156 &amp;gt; 10.141.115.147: ICMP echo reply, id 1, seq 39510, length 64
        0x0000:  4500 0054 4f56 0000 4001 ff0a 0a8c a39c  E..TOV..@.......
        0x0010:  0a8d 7393 0000 3925 0001 9a56 b6b1 9d57  ..s...9%...V...W
        0x0020:  0000 0000 d779 0100 0000 0000 ffff ffff  .....y..........
        0x0030:  ffff ffff ffff ffff ffff ffff ffff ffff  ................
        0x0040:  ffff ffff ffff ffff ffff ffff ffff ffff  ................
        0x0050:  ffff ffff                                ....
02:08:46.517902 IP 10.141.115.147 &amp;gt; 10.140.163.156: ICMP echo request, id 1, seq 39511, length 64
        0x0000:  4500 0054 7d3d 4000 3801 9923 0a8d 7393  E..T}=@.8..#..s.
        0x0010:  0a8c a39c 0800 b41b 0001 9a57 b7b1 9d57  ...........W...W
        0x0020:  0000 0000 5382 0100 0000 0000 ffff ffff  ....S...........
        0x0030:  ffff ffff ffff ffff ffff ffff ffff ffff  ................
        0x0040:  ffff ffff ffff ffff ffff ffff ffff ffff  ................
        0x0050:  ffff ffff                                ....
02:08:46.517937 IP 10.140.163.156 &amp;gt; 10.141.115.147: ICMP echo reply, id 1, seq 39511, length 64
        0x0000:  4500 0054 4f69 0000 4001 fef7 0a8c a39c  E..TOi..@.......
        0x0010:  0a8d 7393 0000 bc1b 0001 9a57 b7b1 9d57  ..s........W...W
        0x0020:  0000 0000 5382 0100 0000 0000 ffff ffff  ....S...........
        0x0030:  ffff ffff ffff ffff ffff ffff ffff ffff  ................
        0x0040:  ffff ffff ffff ffff ffff ffff ffff ffff  ................
        0x0050:  ffff ffff                                ....
02:08:47.520303 IP 10.141.115.147 &amp;gt; 10.140.163.156: ICMP echo request, id 1, seq 39512, length 64
        0x0000:  4500 0054 7d3f 4000 3801 9921 0a8d 7393  E..T}?@.8..!..s.
        0x0010:  0a8c a39c 0800 2411 0001 9a58 b8b1 9d57  ......$....X...W
        0x0020:  0000 0000 e28b 0100 0000 0000 ffff ffff  ................
        0x0030:  ffff ffff ffff ffff ffff ffff ffff ffff  ................
        0x0040:  ffff ffff ffff ffff ffff ffff ffff ffff  ................
        0x0050:  ffff ffff                                ....
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在输出的结果中，可以看到收到的所有ping包的payload都为0xff。新加的”-X”选项可以把整个数据包都抓出来，这对分析一些协议如何工作的时候非常有用。&lt;/p&gt;

&lt;p&gt;上面例子中对tcpdump的功能做了简单的介绍，不过tcpdump的功能远远不止于此，此处列举一些简单常用的tcpdump场景：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// listen on interface eth0
tcpdump -i eth0

// -c packet count, 
tcpdump -c 5 -i eth0

// listen on interface eth0 and port 22
tcpdump -i eth0 port 22

// listen on interface with filter dst and port 
tcpdump -i eth0 dst 10.141.115.147 and port 22

// -w save the capture into the specifed file
tcpdump -w dump.pcap -i eth0 dst 10.141.115.147 and port 22

// -r read the file
tcpdump -r dump.pcap

// listen with specified protocol
tcpdump -i eth0 tcp

// -A, prints the dump in ASCII format, easy to read for HTTP content.
tcpdump -i eth0 -A port 8080

// -XX, prints the dump in hex and ascii formant
tcpdump -i eth0 -XX port 8080

//ip[offset], filter by IP payload, similar for ethernet and tcp..
tcpdump -i eth0 'ip[20] = 0x12 and ip[24:2] = 0x1234' -X
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;iftop&quot;&gt;iftop&lt;/h3&gt;
&lt;p&gt;iftop是一个类top的工具，通过它可以很方便地看到各对端主机对系统网卡的使用排名。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                                     12.5Kb                               25.0Kb                               37.5Kb                               50.0Kb                          62.5Kb
└────────────────────────────────────┴────────────────────────────────────┴────────────────────────────────────┴────────────────────────────────────┴─────────────────────────────────────
10.140.163.156                                                                  =&amp;gt; cnbedc001.china.nsn-net.net                                                      584b    581b    581b
                                                                                &amp;lt;=                                                                                  628b   1.00Kb  1.00Kb
10.140.163.156                                                                  =&amp;gt; 10.141.115.160                                                                  1.05Kb   896b    896b
                                                                                &amp;lt;=                                                                                  160b    320b    320b
255.255.255.255                                                                 =&amp;gt; 10.140.162.241                                                                     0b      0b      0b
                                                                                &amp;lt;=                                                                                 2.48Kb   845b    845b
10.140.163.156                                                                  =&amp;gt; cnbedc002.nsn-intra.net                                                            0b    245b    245b
                                                                                &amp;lt;=                                                                                    0b    208b    208b
10.140.162.255                                                                  =&amp;gt; 10.140.162.223                                                                     0b      0b      0b
                                                                                &amp;lt;=                                                                                    0b    325b    325b
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;nethogs&quot;&gt;nethogs&lt;/h3&gt;
&lt;p&gt;nethogs也是一个类top的工具，通过它可以方便的看到各个进程对系统网卡的使用排名。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NetHogs version 0.8.0

  PID USER     PROGRAM                                                                                                                                DEV        SENT      RECEIVED
?     root     10.140.163.156:8080-10.144.1.24:18507                                                                                                             1.641       0.505 KB/sec
21817 b20yang  sshd: b20yang@pts/4                                                                                                                    eth0       0.154       0.059 KB/sec
?     root     10.140.163.156:8080-10.144.1.24:18510                                                                                                             0.000       0.012 KB/sec
?     root     10.140.163.156:8080-10.144.1.24:18509                                                                                                             0.000       0.012 KB/sec
?     root     10.140.163.156:8080-10.144.1.24:18508                                                                                                             0.000       0.012 KB/sec
?     root     10.140.163.156:8080-10.144.1.24:18506                                                                                                             0.000       0.012 KB/sec
24862 root     ssh                                                                                                                                    eth0       0.000       0.000 KB/sec
?     root     10.140.163.156:8080-10.144.1.24:18392                                                                                                             0.000       0.000 KB/sec
?     root     10.140.163.156:8080-10.144.1.24:18505                                                                                                             0.000       0.000 KB/sec
?     root     10.140.163.156:8080-10.144.1.24:18306                                                                                                             0.000       0.000 KB/sec
?     root     10.140.163.156:8080-10.144.1.24:18393                                                                                                             0.000       0.000 KB/sec
?     root     10.140.163.156:8080-10.144.1.24:18395                                                                                                             0.000       0.000 KB/sec
1217  tomcat7  /usr/lib/jvm/java-7-openjdk-amd64/bin/java                                                                                             eth0       0.000       0.000 KB/sec
?     root     10.140.163.156:8080-10.144.1.24:18394                                                                                                             0.000       0.000 KB/sec
?     root     unknown TCP                                                                                                                                       0.000       0.000 KB/sec

  TOTAL                                                                                                                                                          1.795       0.610 KB/sec
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><summary type="html">前面（一）、（二）、（三）分别介绍了如何剖析系统CPU、内存、磁盘等性能的工具，主要关注点在单个计算机内部；而在接下来的这篇文章中，会将我们的视野伸向更加广阔的互联网络，介绍一些剖析网络性能相关的工具，包括ping，netstat，tcpdump，iftop，nethogs等。</summary></entry><entry><title type="html">Linux系统性能剖析工具（三）</title><link href="http://iamyb.github.io/2016/07/29/Linux-Performance-Utils-3" rel="alternate" type="text/html" title="Linux系统性能剖析工具（三）" /><published>2016-07-29T00:00:00+00:00</published><updated>2016-07-29T00:00:00+00:00</updated><id>http://iamyb.github.io/2016/07/29/Linux-Performance-Utils-3</id><content type="html" xml:base="http://iamyb.github.io/2016/07/29/Linux-Performance-Utils-3">&lt;p&gt;前面&lt;a href=&quot;http://yangbiao.info/2016/07/20/Linux-Performance-Utils-1&quot;&gt;（一）&lt;/a&gt;、&lt;a href=&quot;http://yangbiao.info/2016/07/27/Linux-Performance-Utils-2&quot;&gt;（二）&lt;/a&gt; 两篇文章分别介绍了一些基本的剖析工具，此篇中将会介绍一个更加强大的工具——perf。perf不仅可以统计软件层面的追踪点，如系统调用调度等，还可以追踪统计系统的软硬件事件，如上下文切换（软件事件）、CPU迁移（软件事件）、缓存失效（硬件事件）等。perf中包含一系列的子命令，常用的有list，record，report，sched，top等，下面通过例子列举一些基本用法。&lt;/p&gt;

&lt;h3 id=&quot;perf-sched&quot;&gt;perf sched&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ sudo perf sched record sleep 10
b20yang@ubuntu$ sudo perf sched latency
 -----------------------------------------------------------------------------------------------------------------
  Task                  |   Runtime ms  | Switches | Average delay ms | Maximum delay ms | Maximum delay at       |
 -----------------------------------------------------------------------------------------------------------------
  jbd2/sda1-8:161       |      0.170 ms |        3 | avg:    0.016 ms | max:    0.023 ms | max at: 7188685.842895 s
  unity-scope-loa:2154  |      0.178 ms |        2 | avg:    0.015 ms | max:    0.020 ms | max at: 7188683.454347 s
  nmbd:1514             |      0.337 ms |        3 | avg:    0.013 ms | max:    0.015 ms | max at: 7188682.641534 s
  kworker/1:1H:159      |      0.044 ms |        2 | avg:    0.012 ms | max:    0.015 ms | max at: 7188685.834525 s
  unity-music-dae:2138  |      0.177 ms |        3 | avg:    0.012 ms | max:    0.021 ms | max at: 7188686.454122 s
  smbd:1532             |      0.050 ms |        2 | avg:    0.012 ms | max:    0.016 ms | max at: 7188686.659628 s
  khugepaged:27         |      0.070 ms |        1 | avg:    0.012 ms | max:    0.012 ms | max at: 7188689.716026 s
  watchdog/0:12         |      0.000 ms |        2 | avg:    0.011 ms | max:    0.012 ms | max at: 7188688.148021 s
  kworker/1:1:12299     |      0.337 ms |       15 | avg:    0.011 ms | max:    0.018 ms | max at: 7188685.804037 s
  kworker/0:1H:160      |      0.018 ms |        1 | avg:    0.011 ms | max:    0.011 ms | max at: 7188685.834653 s
  kworker/0:1:14168     |      0.428 ms |       15 | avg:    0.011 ms | max:    0.016 ms | max at: 7188680.816030 s
  kworker/u16:1:15108   |      0.721 ms |       21 | avg:    0.011 ms | max:    0.017 ms | max at: 7188687.328038 s
  systemd-journal:210   |      0.040 ms |        1 | avg:    0.010 ms | max:    0.010 ms | max at: 7188686.523157 s
  rtkit-daemon:1226     |      0.053 ms |        1 | avg:    0.010 ms | max:    0.010 ms | max at: 7188686.659587 s
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上面输出是在“perf sched record”之后，通过”perf sched latency”这条命令解析出来的结果。switch列表示上下文切换的次数，Average Delay表示平均的调度延迟。 perf sched还有其他好几个命令，包括map/replay可以从其他视角看linux系统调度的过程。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ sudo perf sched replay
run measurement overhead: 80 nsecs
sleep measurement overhead: 59119 nsecs
the run test took 1000076 nsecs
the sleep test took 1060769 nsecs
nr_run_events:        1468
nr_sleep_events:      1767
nr_wakeup_events:     760
task      0 (     systemd-timesyn:       364), nr_events: 1
task      &quot;1 (     systemd-timesyn:       375), nr_events: 1
task      2 (     accounts-daemon:       542), nr_events: 1
task      3 (     accounts-daemon:       638), nr_events: 7
task      4 (     accounts-daemon:       651), nr_events: 1
task      5 (      NetworkManager:       546), nr_events: 1
task      6 (      NetworkManager:       647), nr_events: 1
task      7 (      NetworkManager:       664), nr_events: 1
task      8 (      NetworkManager:       695), nr_events: 1
task      9 (            thermald:       549), nr_events: 1
task     10 (            thermald:       694), nr_events: 10
task     11 (        ModemManager:       553), nr_events: 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上面输出是“perf sched replay”的输出结果，可以依次看到上下面切换的过程。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu:~/tmp$ sudo perf sched map
      *A0       7188680.765033 secs A0 =&amp;gt; perf:15304
  *.   A0       7188680.765074 secs .  =&amp;gt; swapper:0
   .  *B0       7188680.765173 secs B0 =&amp;gt; migration/1:14
   .  *.        7188680.765185 secs
  *A0  .        7188680.765186 secs
  *.   .        7188680.765878 secs
   .  *C0       7188680.768033 secs C0 =&amp;gt; rcu_sched:7
   .  *.        7188680.768050 secs
  *D0  .        7188680.768052 secs D0 =&amp;gt; rcuos/0:9
  *.   .        7188680.768083 secs
   .  *C0       7188680.768083 secs
   .  *.        7188680.768089 secs
   .  *C0       7188680.772019 secs
   .  *.        7188680.772029 secs
  *D0  .        7188680.772032 secs
   D0 *E0       7188680.772043 secs E0 =&amp;gt; rcuos/1:18
   D0 *.        7188680.772055 secs
  *.   .        7188680.772068 secs
   .  *F0       7188680.800438 secs F0 =&amp;gt; java:1409
   .  *.        7188680.800483 secs
   .  *G0       7188680.804023 secs G0 =&amp;gt; kworker/1:1:12299
   .  *.        7188680.804036 secs
  *H0  .        7188680.816030 secs H0 =&amp;gt; kworker/0:1:14168
  *.   .        7188680.816039 secs
  *I0  .        7188680.820024 secs I0 =&amp;gt; kworker/u16:1:15108
  *.   .        7188680.820054 secs
   .  *J0       7188680.833868 secs J0 =&amp;gt; thermald:694 上面输出是“perf sched map&quot;的输出结果。信息也很一目了然，可以清楚的看到每个核心上面的调度情况。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;perf-list&quot;&gt;perf list&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ perf list

List of pre-defined events (to be used in -e):
  cpu-cycles OR cycles                               [Hardware event]
  instructions                                       [Hardware event]
  cache-references                                   [Hardware event]
  cache-misses                                       [Hardware event]
  branch-instructions OR branches                    [Hardware event]
  branch-misses                                      [Hardware event]
  bus-cycles                                         [Hardware event]
  ref-cycles                                         [Hardware event]

  cpu-clock                                          [Software event]
  task-clock                                         [Software event]
  page-faults OR faults                              [Software event]
  context-switches OR cs                             [Software event]
  cpu-migrations OR migrations                       [Software event]
  minor-faults                                       [Software event]
  major-faults                                       [Software event]
  alignment-faults                                   [Software event]
  emulation-faults                                   [Software event]
  dummy                                              [Software event]

  L1-dcache-loads                                    [Hardware cache event]
  L1-dcache-load-misses                              [Hardware cache event]
  L1-dcache-stores                                   [Hardware cache event]
  L1-dcache-store-misses                             [Hardware cache event]
  L1-dcache-prefetches                               [Hardware cache event]
  L1-icache-loads                                    [Hardware cache event]
  L1-icache-load-misses                              [Hardware cache event]
  LLC-loads                                          [Hardware cache event]
  LLC-load-misses                                    [Hardware cache event]
  LLC-stores                                         [Hardware cache event]
  LLC-store-misses                                   [Hardware cache event]
  dTLB-loads                                         [Hardware cache event]
  dTLB-load-misses                                   [Hardware cache event]
  dTLB-stores                                        [Hardware cache event]
  dTLB-store-misses                                  [Hardware cache event]
  iTLB-loads                                         [Hardware cache event]
  iTLB-load-misses                                   [Hardware cache event]
  branch-loads                                       [Hardware cache event]
  branch-load-misses                                 [Hardware cache event]
  branch-instructions OR cpu/branch-instructions/    [Kernel PMU event]
  branch-misses OR cpu/branch-misses/                [Kernel PMU event]
  bus-cycles OR cpu/bus-cycles/                      [Kernel PMU event]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;“perf list”命令先列出所有支持的软硬件事件的信息，最后还列出了系统的所有tracepoint。&lt;/p&gt;

&lt;h3 id=&quot;perf-top&quot;&gt;perf top&lt;/h3&gt;

&lt;p&gt;下面是一份简单的C语言示例代码，用gcc编译成目标文件后，在系统一个终端上运行。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define MAX 10000000
int a[MAX];

void loop(){
    for(int i=0;i &amp;lt; MAX; i++) a[i] = i;
}

void main(){
    while(1) {  
		loop();
        sleep(1);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后在另外一个终端上，运行perf top得到如下输出：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ sudo perf top
Samples: 1K of event 'cycles', Event count (approx.): 874746664
Overhead  Shared Object                 Symbol
  50.95%  a.out                         [.] loop
   2.30%  [kernel]                      [k] kallsyms_expand_symbol.constprop.1
   2.23%  libc-2.21.so                  [.] __strstr_sse2
   1.71%  [kernel]                      [k] memcpy
   1.71%  perf                          [.] 0x000000000005a0b7
   1.68%  [kernel]                      [k] vsnprintf
   1.60%  [kernel]                      [k] format_decode
   1.14%  [kernel]                      [k] number.isra.2
   1.14%  [kernel]                      [k] module_get_kallsym
   1.07%  libc-2.21.so                  [.] _int_malloc
   1.02%  libc-2.21.so                  [.] __GI___strcmp_ssse3
   0.86%  [kernel]                      [k] string.isra.7
   0.59%  [kernel]                      [k] apparmor_capable
   0.57%  libc-2.21.so                  [.] _IO_getdelim
   0.57%  [kernel]                      [k] strnlen
   0.54%  libc-2.21.so                  [.] __libc_calloc
   0.51%  perf                          [.] 0x0000000000061b9c
   0.51%  perf                          [.] 0x000000000009fb63
   0.51%  [kernel]                      [k] rcu_check_callbacks
   0.50%  libc-2.21.so                  [.] __memset_sse2
   0.50%  libc-2.21.so                  [.] __memcpy_sse2
   0.49%  [kernel]                      [k] clear_page_c
   0.49%  [kernel]                      [k] copy_user_generic_string
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上面输出结果的最左侧一栏，可以看到该loop函数占用了系统的50%的cpu时间。通过方向键-&amp;gt;进入loop函数，可以看到loop函数各个指令的cpu资源使用率。（gcc编译的时候加上-ggdb选项可以在annotate里面显示汇编语言对应的源代码）。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;       │    Disassembly of section .text:
       │
       │    0000000000400536 &amp;lt;loop&amp;gt;:
       │    loop():
       │      push   %rbp
       │      mov    %rsp,%rbp
       │      movl   $0x0,-0x4(%rbp)
       │    ↓ jmp    20
 12.81 │ d:   mov    -0x4(%rbp),%eax
  1.32 │      cltq
  1.22 │      mov    -0x4(%rbp),%edx
       │      mov    %edx,0x601080(,%rax,4)
 49.25 │      addl   $0x1,-0x4(%rbp)
 13.65 │20:   cmpl   $0x98967f,-0x4(%rbp)
 21.75 │    ↑ jle    d
       │      pop    %rbp
       │    ← retq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上面输出结果的左侧信息是表示这些指令运行时间占该函数总运行事件的比例。&lt;/p&gt;

&lt;h3 id=&quot;perf-report&quot;&gt;perf report&lt;/h3&gt;
&lt;p&gt;还是上面C语言的例子，先用record命令“perf record -g ./a.out”记录统计目标文件执行的事件统计数据，然后再用“perf report”分析结果。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ sudo perf report -g flat  

Samples: 1K of event 'cycles', Event count (approx.): 876982948, Thread: a.out(19784)
  Children      Self  Comma  Shared Object      Symbol                                                                                                                                   ◆
+   99.63%     0.00%  a.out  [unknown]          [.] 0x087e258d4c544155                                                                                                                   ▒
+   99.63%     0.00%  a.out  libc-2.21.so       [.] __libc_start_main                                                                                                                    ▒
+   99.63%     0.00%  a.out  a.out              [.] main                                                                                                                                 ▒
+   99.63%    69.71%  a.out  a.out              [.] loop                                                                                                                                 ▒
+   29.42%     1.07%  a.out  [kernel.kallsyms]  [k] page_fault                                                                                                                           ▒
+   28.43%     0.08%  a.out  [kernel.kallsyms]  [k] do_page_fault                                                                                                                        ▒
+   28.26%     0.17%  a.out  [kernel.kallsyms]  [k] __do_page_fault                                                                                                                      ▒
+   27.76%     0.25%  a.out  [kernel.kallsyms]  [k] handle_mm_fault                                                                                                                      ▒
+   26.40%     0.00%  a.out  [kernel.kallsyms]  [k] alloc_pages_vma                                                                                                                      ▒
+   26.40%     0.00%  a.out  [kernel.kallsyms]  [k] __alloc_pages_nodemask                                                                                                               ▒
+   22.48%     0.00%  a.out  [kernel.kallsyms]  [k] do_huge_pmd_anonymous_page                                                                                                           ▒
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在上面输出中，左侧的overhead被分成两个部分，一个是children, 一个是self。children包含了该函数所有子函数调用的sample，self则是只包含本函数的overhead。&lt;/p&gt;

&lt;h3 id=&quot;perf-stat&quot;&gt;perf stat&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu:~/tmp$ perf stat -e L1-dcache-loads:k dd if=/dev/zero of=/dev/null count=1000
1000+0 records in
1000+0 records out
512000 bytes (512 kB) copied, 0.000632926 s, 809 MB/s

 Performance counter stats for 'dd if=/dev/zero of=/dev/null count=1000':

           564,068      L1-dcache-loads

       0.001411362 seconds time elapsed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;通过选项“-e”可以告诉“perf stat”命令需要统计哪些事件，比如上例中指定了“L1-dcache-loads:k”，后面的k限定了发生在内核空间内的该事件（限定符u为用户空间）。&lt;/p&gt;</content><author><name></name></author><summary type="html">前面（一）、（二） 两篇文章分别介绍了一些基本的剖析工具，此篇中将会介绍一个更加强大的工具——perf。perf不仅可以统计软件层面的追踪点，如系统调用调度等，还可以追踪统计系统的软硬件事件，如上下文切换（软件事件）、CPU迁移（软件事件）、缓存失效（硬件事件）等。perf中包含一系列的子命令，常用的有list，record，report，sched，top等，下面通过例子列举一些基本用法。</summary></entry><entry><title type="html">Linux系统性能剖析工具（二）</title><link href="http://iamyb.github.io/2016/07/27/Linux-Performance-Utils-2" rel="alternate" type="text/html" title="Linux系统性能剖析工具（二）" /><published>2016-07-27T00:00:00+00:00</published><updated>2016-07-27T00:00:00+00:00</updated><id>http://iamyb.github.io/2016/07/27/Linux-Performance-Utils-2</id><content type="html" xml:base="http://iamyb.github.io/2016/07/27/Linux-Performance-Utils-2">&lt;p&gt;如果一个系统负载过高时，通过&lt;a href=&quot;http://yangbiao.info/2016/07/20/Linux-Performance-Utils-1&quot;&gt;Linux性能剖析工具（一）&lt;/a&gt;中介绍的工具，可以看出当前系统大概的状态，了解到比如什么任务的占用的CPU较多等信息。那知道这些信息后，接下来应该怎么办呢？——接下来就应该去试图找出函数级别的热点代码了。本篇将会简单介绍strace(system call  trace),ltrace(library trace)在函数性能剖析中的用法。&lt;/p&gt;

&lt;h3 id=&quot;strace&quot;&gt;strace&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ strace -c dd bs=1024 count=1024k if=/dev/zero of=/dev/null
1048576+0 records in
1048576+0 records out
1063256064 bytes (1.1 GB) copied, 40.2985 s, 26.4 MB/s
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 51.91    0.003715           0   1048579           read
 48.09    0.003442           0   1048579           write
  0.00    0.000000           0        18        11 open
  0.00    0.000000           0        10           close
  0.00    0.000000           0         5           fstat
  0.00    0.000000           0         1           lseek
  0.00    0.000000           0        11           mmap
  0.00    0.000000           0         4           mprotect
  0.00    0.000000           0         2           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         4           rt_sigaction
  0.00    0.000000           0         3         3 access
  0.00    0.000000           0         2           dup2
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00    0.007157               2097223        14 total
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;strace, 系统调用（system call trace）。通过选项&lt;strong&gt;-c&lt;/strong&gt;可以统计到该任务各个系统调用的运行时间，从上例中的输出结果可以看到，read、write系统调用占了几乎100%的执行时间，另外从calls列也可以看到read/write系统调用的次数基本符合dd命令的count输入，这些数据基本符合我们对dd任务的预期。再看下面的例子：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ dd bs=1G count=1k if=/dev/zero of=/dev/null&amp;amp;
[1] 3087
b20yang@ubuntu$ strace -T -p 3087
read(0, &quot;0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&quot;..., 1073741824) = 1073741824 &amp;lt;0.574003&amp;gt;
write(1, &quot;\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&quot;..., 1073741824) = 1073741824 &amp;lt;0.000011&amp;gt;
read(0, &quot;0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&quot;..., 1073741824) = 1073741824 &amp;lt;0.572800&amp;gt;
write(1, &quot;\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&quot;..., 1073741824) = 1073741824 &amp;lt;0.000013&amp;gt;
read(0, &quot;0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&quot;..., 1073741824) = 1073741824 &amp;lt;0.573986&amp;gt;
write(1, &quot;\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&quot;..., 1073741824) = 1073741824 &amp;lt;0.000010&amp;gt;
read(0, &quot;0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&quot;..., 1073741824) = 1073741824 &amp;lt;0.573231&amp;gt;
write(1, &quot;\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&quot;..., 1073741824) = 1073741824 &amp;lt;0.000011&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;通过选项-p [pid]可以将strace attach到正在运行的某个进程上，而选项-T则是告知strace统计每次系统调用的时间。上例中pid 3087为dd任务的进程id，同样从输出中可以看到该进程一直在所预期的read/write。&lt;/p&gt;

&lt;h3 id=&quot;ltrace&quot;&gt;ltrace&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ ltrace -c dd bs=1024 count=1k if=/dev/zero of=/dev/null
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB) copied, 0.218582 s, 4.8 MB/s
% time     seconds  usecs/call     calls      function
------ ----------- ----------- --------- --------------------
 48.64    0.091193          89      1024 read
 48.21    0.090370          88      1024 write
  0.34    0.000632         316         2 dcgettext
  0.22    0.000421          70         6 strchr
  0.22    0.000405         135         3 __fprintf_chk
  0.20    0.000383          95         4 sigaction
  0.19    0.000354          70         5 strlen
  0.19    0.000351          87         4 close
  0.19    0.000350          70         5 __errno_location
  0.17    0.000313         313         1 setlocale
  0.10    0.000187          93         2 open
  0.09    0.000175          87         2 dup2
  0.08    0.000154          77         2 localeconv
  0.08    0.000148          74         2 sigaddset
  0.08    0.000148          74         2 sigismember
  0.08    0.000146          73         2 clock_gettime
  0.08    0.000142          71         2 __ctype_b_loc
  0.08    0.000141          70         2 __freading
  0.07    0.000140          70         2 __strtoul_internal
  0.05    0.000089          89         1 fclose
  0.05    0.000087          87         1 lseek
  0.04    0.000084          84         1 __cxa_atexit
  0.04    0.000082          82         1 __sprintf_chk
  0.04    0.000082          82         1 getpagesize
  0.04    0.000077          77         1 bindtextdomain
  0.04    0.000077          77         1 getopt_long
  0.04    0.000076          76         1 dcngettext
  0.04    0.000076          76         1 memmove
  0.04    0.000075          75         1 sigemptyset
  0.04    0.000075          75         1 strrchr
  0.04    0.000075          75         1 malloc
  0.04    0.000074          74         1 textdomain
  0.04    0.000074          74         1 getenv
  0.04    0.000071          71         1 fileno
  0.04    0.000070          70         1 __fpending
  0.04    0.000070          70         1 fflush
------ ----------- ----------- --------- --------------------
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;ltrace，和strace的功能非常类似，甚至很多命令选项都一样，如ltrace也可以attach到指定进程上，也可以指定-T选项统计每个调用的时间。从上面的输出结果就可以看出来，最大的区别是：除了系统调用外ltrace还追踪了一些库函数的调用。这哥俩其实从实现的原理上也很类似：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ ltrace -e trace=ptrace ltrace uptime
ptrace(PTRACE_SYSCALL, 5293, 0, SIG_0)  = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=5293, si_status=SIGTRAP, si_utime=0, si_stime=0} ---
ptrace(PTRACE_GETREGSET, 5293, NT_PRSTATUS, [{0x66a6c0, 216}]) = 0
close(2ptrace(PTRACE_SYSCALL, 5293, 0, SIG_0)  = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=5293, si_status=SIGTRAP, si_utime=0, si_stime=0} ---
ptrace(PTRACE_GETREGSET, 5293, NT_PRSTATUS, [{0x66a6c0, 216}]) = 0
)                                = 0
ptrace(PTRACE_SYSCALL, 5293, 0, SIG_0)  = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_TRAPPED, si_pid=5293, si_status=SIGTRAP, si_utime=0, si_stime=0} ---
ptrace(PTRACE_GETREGSET, 5293, NT_PRSTATUS, [{0x66a6c0, 216}]) = 0
exit_group(0)                           = ?
ptrace(PTRACE_SYSCALL, 5293, 0, SIG_0)  = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=5293, si_status=0, si_utime=0, si_stime=0} ---
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;无论是strace还是ltrace，他们都是通过ptrace系统调用来实现的。上面命令选项&lt;strong&gt;-e&lt;/strong&gt;告诉ltrace仅仅追踪指定的ptrace系统调用，类似地，也可以从strace中得到对ptrace大量的调用。因此，这哥俩还有一个特性也很相似，就是trace的开销都很大，这是题外话。&lt;/p&gt;</content><author><name></name></author><summary type="html">如果一个系统负载过高时，通过Linux性能剖析工具（一）中介绍的工具，可以看出当前系统大概的状态，了解到比如什么任务的占用的CPU较多等信息。那知道这些信息后，接下来应该怎么办呢？——接下来就应该去试图找出函数级别的热点代码了。本篇将会简单介绍strace(system call trace),ltrace(library trace)在函数性能剖析中的用法。</summary></entry><entry><title type="html">Linux系统性能剖析工具（一）</title><link href="http://iamyb.github.io/2016/07/20/Linux-Performance-Utils-1" rel="alternate" type="text/html" title="Linux系统性能剖析工具（一）" /><published>2016-07-20T00:00:00+00:00</published><updated>2016-07-20T00:00:00+00:00</updated><id>http://iamyb.github.io/2016/07/20/Linux-Performance-Utils-1</id><content type="html" xml:base="http://iamyb.github.io/2016/07/20/Linux-Performance-Utils-1">&lt;p&gt;最近抽空翻了System Performance这本书，内容主要是讲&lt;strong&gt;如何使用工具&lt;/strong&gt;去查找Linux系统的性能瓶颈。前面我特意把&lt;strong&gt;“如何使用工具“&lt;/strong&gt;这几个字加粗了，除了这就是这本书的核心之外，还有是因为这里面其实含有两层意思：一是字面的意思——怎么使用这些工具以及通过这些个工具能够获取到哪些信息；二是关于工具使用的时间和场合，应该在什么时候使用什么样的工具。我觉得第二点尤为重要，Linux系统经过这么些年的开源演化，伴随着也产生了很多优秀的系统剖析工具，不过对于需要做软件优化的工程师——特别是新人来说，可能就会懵逼了。所以把这些工具梳理出来，系统化叙述成册以便索引是很重要的。&lt;/p&gt;

&lt;p&gt;这里我把书中提到的工具并结合一些例子做简单总结，因为篇幅关系及循序渐进的需要，我会分成2~3篇文章陆陆续续的发出来。在此篇里面，主要关注一些基本的命令的用法，如uptime, top, iostat, vmstat等。把它们集中在这里，一个是因为这些命令都比较简单，二是确实非常的常用，可能出问题了第一个想到的就是这些命令了。比如可能首先会用uptime看一下整个系统最近的负载，如果load很高的话然后就会用top去看看哪些任务占用的CPU资源，然后再去检查某一个进程等等。&lt;/p&gt;

&lt;p&gt;对于每个命令，我会先贴上在我的机器上执行的输出，然后加以注释，如果有需要的话也会举例加以说明。就此开始吧：&lt;/p&gt;

&lt;h3 id=&quot;uptime&quot;&gt;uptime&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ uptime   
23:49:23 up 79 days,  5:13,  2 users,  load average: 0.00, 0.01, 0.05  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;最后三个数字分别表示过去1分钟，5分钟，15分钟系统的负载，可以依此判断系统负载最近的变化趋势。&lt;/p&gt;

&lt;h3 id=&quot;tophtop&quot;&gt;top/htop&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ top
%Cpu(s):  0.2 us,  0.3 sy,  0.0 ni, 99.5 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:   3880708 total,  3711540 used,   169168 free,  1347968 buffers
KiB Swap:  2042876 total,   593940 used,  1448936 free.   834140 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 1839 b20yang   20   0 1690320 236636  17060 S   0.7  6.1 453:30.65 compiz
    1 root      20   0  117196   4452   3148 S   0.0  0.1   1:30.42 systemd
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.52 kthreadd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;相比uptime，top会显示更多的信息，包括进程级别CPU LOAD、交换分区和物理内存的使用率等。可以通过top找到哪些进程占用了比较多的系统资源。那么如果通过top找到了cpu load很高的进程之后，那接下来应该怎么办呢？接下来就应该去分析这个进程的code execution path，找出为什么用了这么多的资源。 htop是top的高级版本。&lt;/p&gt;

&lt;h3 id=&quot;mpstat&quot;&gt;mpstat&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ mpstat -P ALL 1
02:24:11 PM  CPU   %user   %nice    %sys %iowait    %irq   %soft  %steal   %idle    intr/s
02:24:12 PM  all    0.00    0.00    0.07    0.00    0.00    0.00    0.00   99.93    618.00
02:24:12 PM    0    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00      0.00
02:24:12 PM    1    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00      0.00
02:24:12 PM    2    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00 4294967288.00
02:24:12 PM    3    0.00    0.00    1.98    0.00    0.00    0.00    0.00   98.02      0.00
02:24:12 PM    4    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00      0.00
02:24:12 PM    5    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00      0.00
02:24:12 PM    6    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00      0.00
02:24:12 PM    7    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00      0.00
02:24:12 PM    8    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00      0.00
02:24:12 PM    9    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00      0.00
02:24:12 PM   10    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00      0.00
02:24:12 PM   11    0.00    0.00    0.00    0.00    0.00    0.00    0.00  100.00      0.00
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;用这个命令可以很方便的看到CPU各个核心之间负载是否均衡。&lt;/p&gt;

&lt;h3 id=&quot;iostat&quot;&gt;iostat&lt;/h3&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ iostat 1
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.00    0.00    0.00    0.00    0.00  100.00

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               0.00         0.00         0.00          0          0
sdb               0.00         0.00         0.00          0          0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;iostat主要用来检查系统输入输出设备的使用状态，比如磁盘的tps等。如果我们在一个终端执行&lt;strong&gt;“dd bs=1014 count=1024k if=/dev/zero of=/tmp/tmp.bin”&lt;/strong&gt;，同时在另外一个终端上面执行命令iostat 1，那么可以看到sda上面的kB_wrtn/s急剧上涨。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ iostat 1
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.51    0.00    0.00   95.96    0.00    3.54

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda              73.00         4.00     73728.00          4      73728
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;vmstat&quot;&gt;vmstat&lt;/h3&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0 613484 1236068 382688 750232    0    0     0     0   66  166  0  0 99  0  0
 0  0 613484 1236068 382688 750232    0    0     0     0   64  178  0  0 100  0  0
 0  0 613480 1236068 382688 750232   12    0    12     0   61  158  1  0 100  0  0
 0  0 613480 1236068 382688 750232    0    0     0     0   52  126  0  1 100  0  0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;vmstat主要用来检查系统内存，交换分区、磁盘块设备等状态。类似的，也可以看看命令&lt;strong&gt;“dd bs=1014 count=1024k if=/dev/zero of=/tmp/tmp.bin”&lt;/strong&gt;是如何影响vmstat的。&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;b20yang@ubuntu$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 3  2 611476 1163584 389952 822688    0    0     5    16    1    1  0  0 99  0  0
 0  1 611476 1078792 389956 907204    0    0     4 58816  268  352  1  1 25 73  0
 1  3 611476 1006452 389964 979660    0    0     0 49240  227  267  2  9 15 75  0
 1  2 611476 965156 389976 1020360    0    0     4 122084  215  293  1  4  0 95  0
 1  1 611476 828852 389976 1153044    0    0     0 81920  293  414  0  1 17 82  0
 0  1 611476 748700 389984 1230996    0    0     8 140064  245  276  2  7 31 60  0
 0  2 611476 687552 389988 1289972    0    0     4 131072  190  271  1  7 10 82  0
 0  2 611476 687392 389992 1290024    0    0     4 131072  120 8305  1  2  0 98  0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name></name></author><summary type="html">最近抽空翻了System Performance这本书，内容主要是讲如何使用工具去查找Linux系统的性能瓶颈。前面我特意把“如何使用工具“这几个字加粗了，除了这就是这本书的核心之外，还有是因为这里面其实含有两层意思：一是字面的意思——怎么使用这些工具以及通过这些个工具能够获取到哪些信息；二是关于工具使用的时间和场合，应该在什么时候使用什么样的工具。我觉得第二点尤为重要，Linux系统经过这么些年的开源演化，伴随着也产生了很多优秀的系统剖析工具，不过对于需要做软件优化的工程师——特别是新人来说，可能就会懵逼了。所以把这些工具梳理出来，系统化叙述成册以便索引是很重要的。</summary></entry><entry><title type="html">推荐一些Linux基础学习书籍</title><link href="http://iamyb.github.io/2015/07/08/My-Linux-Tutorials" rel="alternate" type="text/html" title="推荐一些Linux基础学习书籍" /><published>2015-07-08T00:00:00+00:00</published><updated>2015-07-08T00:00:00+00:00</updated><id>http://iamyb.github.io/2015/07/08/My-Linux-Tutorials</id><content type="html" xml:base="http://iamyb.github.io/2015/07/08/My-Linux-Tutorials">&lt;p&gt;这是我给我司同事推荐的关于Linux基础学习的一些书籍，稍作整理放到这里。其中1/2/3三本属于入门书籍，4/5两本属于进阶书籍，最后几本则稍微难点。&lt;/p&gt;

&lt;h4 id=&quot;1-the-linux-command-line&quot;&gt;1. The Linux Command Line&lt;/h4&gt;

&lt;p&gt;这本书是我见过的介绍Linux命令行最好的材料，也是较好的Linux入门书籍之一。整本书的结构非常清晰，书中提到的命令行也是恰到好处的简单——但确实又是一些非常有用、常用的命令，即使没怎么接触过Linux的同学，读起来应该也不用花多少精力，而且对于每个专题下面作者还会有相应介绍，有助于理解背景和使用场景。这本书大家最好能够全部阅读，推荐大家一边阅读一边找台Linux的机器上尝试一下，估计你们最多一个星期的晚上就能看完。&lt;/p&gt;

&lt;h4 id=&quot;2-beginning-linux-programming-4th-edition&quot;&gt;2. Beginning Linux Programming 4th Edition&lt;/h4&gt;

&lt;p&gt;Linux 编程的入门书籍，这本书大家可以跳着看。对于软件人员来说，我推荐大家阅读第3章、第4章、第7章文件锁一节、以及第11章到15章。虽然这本书部分内容和APUE（Advanced Programming in Unix Env）有些重叠——比如像IPC之类核心部分，但是考虑到APUE介绍这些内容时，通常还会介绍其他类UNIX的实现，可能会对大家的理解造成某些混淆。所以我还是推荐大家看这部分内容，应该花不了多长时间。&lt;/p&gt;

&lt;h4 id=&quot;3-the-unix-programming-environment&quot;&gt;3. The Unix Programming Environment&lt;/h4&gt;

&lt;p&gt;Unix的诞生地Bell实验室计算机的科学家、《C语言程序设计》的作者Kernighan写1983年写的，经典成就经典。这是我接触的第一本Unix/Linux的学习书籍，多年以后想来依旧很美好。不推荐大家都去看了，仅仅推荐那些有情怀的同志们去看看。&lt;/p&gt;

&lt;h4 id=&quot;4-advanced-programming-in-the-unix-environment&quot;&gt;4. Advanced Programming in the Unix Environment&lt;/h4&gt;
&lt;p&gt;简称APUE，被称为Unix及Linux系统编程领域“圣经”。这本书被人推崇的原因——用现在流行的话来说，就是“干货十足”，书中对于进程、进程间的关系、进程控制和同步、线程、线程控制和同步、Daemon、IPC、同步IO异步IO等内容的讲解是本书的精华部分，当你看完这些内容，然后去实践一段时间（比如看看平台CCS的代码），然后再回来看这书可能就会有这种感受。这本书是一本大块头的书，英文版本有1000多页，中译版本有700多页（中文翻译的不怎么样）。虽然如此，我还是推荐大家耐心的读一下整本书籍，同时最好能够把里面的一些代码示例都敲到电脑里面试一下。&lt;/p&gt;

&lt;h4 id=&quot;5-linuxkerneldevelopment3rdedition&quot;&gt;5. Linux.Kernel.Development.3rd.Edition&lt;/h4&gt;
&lt;p&gt;Linux内核入门书籍。Linux内核有多少行呢？3.17.x版本的大概是1200多万行，最新的.0版本应该更多，这么庞大的一个代码库对大家来说简直是汪洋大海！所以给大家推荐此书。考虑有二：一个是简单——如果大家有前面的基础之后，看下来应该不会有什么大碍，不至于退却；另一个是到位，内容覆盖应该都是很核心的内容，可以很好的让你建立一个知识图谱，又摒弃了很多操作系统设计里面的很多细枝末节。这本书最好全部阅读。&lt;/p&gt;

&lt;h4 id=&quot;6-linux-kernel-driver-and-professional-linux-kernel-architecture&quot;&gt;6. Linux Kernel Driver and Professional Linux Kernel Architecture&lt;/h4&gt;
&lt;p&gt;这两本书可以作为参考书籍。你需要了解某些内容的时候，如果这两本书里面有，就可以找到对应的章节去翻一下。比如前段时间，在我司项目上需要共享内存，但DSP使用的物理地址的模型，ARM使用的虚拟地址模型，怎么办呢？我就挑选了Linux Kernel Driver的DMA章节看了一下，然后找了一个比较合理的解决方案出来；另如，之前一直有ARM上面的时钟精度不够的问题，为了了解能不能满足我们的实时性要求，我就挑了PLKA里面的时间管理相关的章节看了看。如此等等，不过大家对这两本书不用强求。&lt;/p&gt;

&lt;h4 id=&quot;7-深入调试的技术和工具debughacks中文版&quot;&gt;7. 深入调试的技术和工具(Debug.Hacks中文版)&lt;/h4&gt;
&lt;p&gt;工具书。这本书我推荐大家在开始干活的时候就去大概晃一眼。对Linux应用层的程序员来说，strace, valgrind, gdb, coredump等都是必要的调试工具，Kernel的一些调试技术大家可在需要的时候去看看。&lt;/p&gt;

&lt;h4 id=&quot;8-tcpip-详解卷一&quot;&gt;8. TCP/IP 详解（卷一）&lt;/h4&gt;
&lt;p&gt;推荐大家去晃一下ARP，IP，TCP，UDP等基础协议内容。&lt;/p&gt;</content><author><name></name></author><summary type="html">这是我给我司同事推荐的关于Linux基础学习的一些书籍，稍作整理放到这里。其中1/2/3三本属于入门书籍，4/5两本属于进阶书籍，最后几本则稍微难点。</summary></entry><entry><title type="html">Unix高级环境编程中的一个Bug</title><link href="http://iamyb.github.io/2013/08/06/A-Bug-Found-inside-APUE" rel="alternate" type="text/html" title="Unix高级环境编程中的一个Bug" /><published>2013-08-06T00:00:00+00:00</published><updated>2013-08-06T00:00:00+00:00</updated><id>http://iamyb.github.io/2013/08/06/A-Bug-Found-inside-APUE</id><content type="html" xml:base="http://iamyb.github.io/2013/08/06/A-Bug-Found-inside-APUE">&lt;p&gt;这个bug发现于Unix高级环境编程2013年出版的第三版第17章第7节——An Open Server，在这一节里作者开发了一个Client-Server结构的示例程序，让读者可以把本章前面几节的一些内容——其中包括Unix Naming Domain Socket, Unique Connection和Passing File Descriptor等知识可以很好地融会贯通起来。不过这个例子在IA-64的Linux的平台下运行时会遇到一个bug，这个bug会导致Client收到的数据和Server发送的数据不匹配，使程序运行时不能产生预期的行为。&lt;/p&gt;

&lt;p&gt;17.7示例的主要功能是为了客户端和服务器的文件共享，通过两者之间共享文件描述符而不是的文件内容使进程间的文件共享更加高效。其中客户端和服务器端通过命名的Unix域套接字进行进程间的IPC通信。大概的流程是这样的：一、客户端可以向服务器端发送打开指定路径的文件的请求；二、服务器收到客户端的请求后，会尝试打开客户端指定路径的文件，把打开的文件描述符回传给客户端；接下来客户端可以直接使用文件所支持的操作来访问文件的内容了。为此，作者开了几个API用来发送文件描述符、接受文件描述符以及对应的错误处理：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;int send_fd(int fd, int fd_to_send);
int recv_fd(int fd, ssize_t (*userfunc)(int, const void*, size_t));
int send_err(int fd, int status, const char *errmsg);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;通过send_fd接口，可以将文件描述符fd_to_send通过套接字fd发送给目标进程；相应地，接受方可以通过recv_fd接受其他进程发给自己的文件描述符。&lt;strong&gt;事实上，本篇博客要说的bug就是出现在这两个函数之中！&lt;/strong&gt;在调用套接字的接口sendmsg发送消息之前，send_fd需要对消息进行初始化，这个消息对应的结构体类型为msghdr，其中包括存放用户数据的缓存、控制消息（Control Message，Linux中的man page可以看到控制消息的详细定义cmsghdr和说明）、控制消息长度等结构体成员。&lt;strong&gt;而问题就是出在msghdr结构体的初始化这里。&lt;/strong&gt;摘录书中的一小段代码如下：&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#define CONTROLLEN CMSG_LEN(sizeof(int))
int send_fd(int fd, int fd_to_send)
{
	//...
	struct msghdr msg;
	cmptr-&amp;gt;cmsg_len = CONTROLLEN;
	msg.msg_control = cmptr;
	msg.msg_controllen = CONTROLLEN;
	*(int*)CMSG_DATA(cmptr) = fd_to_send;
	//...
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;msg的成员msg_controllen表示控制消息的长度。此处，msg_controllen会被赋值成CONTROLLEN这个宏的值，而这个宏被定义成CMSG_LEN(sizeof(int))。CMSG_LEN是POSIX定义的一个宏，用来计算控制消息的长度。控制消息包括控制消息的头和控制消息承载的payload数据，sizeof(int)就是此例所需的payload长度——用来存放一个文件描述符；而后CSMG_LEN宏会加上控制消息头长度，算出来就是控制消息的长度了。&lt;/p&gt;

&lt;p&gt;在x86_64的Linux环境下，控制消息头的长度为16个字节，所以在此例中控制消息长总共为20个字节。send_fd在初始化消息完成后，会调用系统调用sendmsg将其发出，然后客户端调用recvmsg将其接收，然后解析控制消息得到发送过来的文件描述符。但是执行此程序后，发现收到的文件描述符值和发送的文件描述符的值不匹配，同时&lt;strong&gt;发现msg_controllen长度也变了——发送的值是20个字节而收到的却是24字节。那么问题出在什么地方呢？检查内核系统调用sendmsg的调用栈源代码可以看到，在x86-64的运行环境下，当消息从用户空间传到内核空间时，控制消息的长度被要求与64位对齐，所以20个字节的长度会被修改成24个字节。&lt;strong&gt;这里就是客户端和服务器段控制消息的长度不一的问题所在了。&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;事实上，在cmsg的mannual page里面有如下一段关于cmsg初始化的描述，msg_controllen需要使用CMSG_SPACE的这个宏来初始化——CMSG_SPACE这个宏会自动控制消息作对齐操作。而Unix高级环境编程书中使用CMSG_LEN宏来初始化msg_controllen的方式是不对的。&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;To create ancillary data, first initialize the msg_controllen member of the msghdr with the length of the control  message buffer.  Use CMSG_FIRSTHDR() on the msghdr to get the first control message and CMSG_NXTHDR() to get all subsequent ones.  In each control message, initialize cmsg_len (with CMSG_LEN()),  the  other  cmsghdr header fields, and the data portion using CMSG_DATA().  Finally, the msg_controllen field of the msghdr should be set to the sum of the CMSG_SPACE() of the length of all control messages in the buffer.  For more  information on the msghdr, see recvmsg(2).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;以上就是关于这个bug的一个总结。：）&lt;/p&gt;</content><author><name></name></author><summary type="html">这个bug发现于Unix高级环境编程2013年出版的第三版第17章第7节——An Open Server，在这一节里作者开发了一个Client-Server结构的示例程序，让读者可以把本章前面几节的一些内容——其中包括Unix Naming Domain Socket, Unique Connection和Passing File Descriptor等知识可以很好地融会贯通起来。不过这个例子在IA-64的Linux的平台下运行时会遇到一个bug，这个bug会导致Client收到的数据和Server发送的数据不匹配，使程序运行时不能产生预期的行为。</summary></entry><entry><title type="html">Goto语句</title><link href="http://iamyb.github.io/2013/05/04/Goto-State" rel="alternate" type="text/html" title="Goto语句" /><published>2013-05-04T00:00:00+00:00</published><updated>2013-05-04T00:00:00+00:00</updated><id>http://iamyb.github.io/2013/05/04/Goto-State</id><content type="html" xml:base="http://iamyb.github.io/2013/05/04/Goto-State">&lt;p&gt;很多程序员可能听说过，“不要使用Goto语句”这样的观点。但是现在计算机系的学生可能很少有听到过这个原则背后有着怎么样的历史背景了。关于是否使用Goto语句、什么场合使用Goto语句曾经在编程史上引发激烈的辩论，这些争论从上个世纪的60年代一直延续到本世纪初，其中的参与者包括大名鼎鼎Dijkstra Edsger、Knuth Donald还有Linus Troald等等，大部分同学应该对这些计算机发展史上里程牌式的名字非常熟悉。以现在的眼光回去看当时这些大牛们的文章，可能会觉得这些争论已经了无意义或者类似的问题已经不复存在了，但是设身处地的回到他们各自的时代，就会看到他们的讨论对计算机编程语言演进的影响。&lt;/p&gt;

&lt;p&gt;上个世纪60年代，计算机发展还处于上古时代。硬件方面还是使用晶体管作为逻辑运算单元，软件方面支持多任务的现代操作系统也还未成型，当时的计算机主要还是用来做科学运算的工具。在这样的历史背景下，1968年3月，Dijkstra在ACM发表了一篇文章Go To Statement Considered Harmful，阐述了他对Goto语句以及编程方便的一些观点。在这篇文章中，Dijkstra认为”Goto使用的越多，程序的质量越差“，所以程序中要尽可能的消除Goto语句。这样做目的很简单，就是要尽可能的消除程序中的面条式代码（Spahetti Code）。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/spaghetti-code-wood.jpg&quot; alt=&quot;_config.yml&quot; /&gt;&lt;/p&gt;

&lt;p&gt;什么是面条式代码呢？它指的是计算机程序中那些逻辑复杂、各分支之间跳来跳去绞在一起的代码。说到这，就不能不先了解一下当时流行的编程语言了。Dijkstra发表文章时，计算机语言还没有Swtich，For, While等控制结构，当时的程序员只能使用if-thens+goto来实现我们现在经常使用各种控制功能。但是，计算机的本质上是一个有限状态机，通过状态之间条件跳转或者循环实现各种功能。因此，在底层机器码和汇编代码级别是不可能消除跳转指令的。重复代码的使用或者说面条式的代码是伴随着计算机诞生而无法消除的，Dijkstra在他的文章中也承认了这一点。例如，由汇编语言编写的代码就是一种面条式的代码，而我们不可能消除汇编代码的jmp跳转指令。&lt;/p&gt;

&lt;p&gt;Dijkstra发表这篇文章之后，引发了业界关于Goto语句大讨论，很多人对Dijkstra的观点感到不安，Dijkstra也因此收到了很多别人辱骂他的信件。与此同时，结构化编程（Structure Programming）的理论也正悄悄的发展起来，结构化编程试图在计算机语言中引入子函数、循环控制、条件控制等概念，包括for, while, do while, switch case等等，能够让写出来的程序更加容易修改和维护。1972年，Knuth发表了一篇文章Structured Programming with Go to statements，总结了Goto语句的历史背景、目前业界使用情况以及他自己的一些观点：Knuth 认为大部分情况下最好避免使用goto语句，但是在一些情况下，在程序中使用Goto语句是无害的，比如错误处理 、嵌套循环；还有比如even indicator。有意思的是，Knuth提到的有些情况现在已经发展成发展成现代编程语言的特性了，比如even indicator就是后来我们在各种编程语言中常常见到的switch case。&lt;/p&gt;

&lt;p&gt;时间转到2003年，有个Linux内核开发新人从Linux的内核代码里找到了一段使用Goto的代码，他把这段代码修改了一下——消除了Goto语句，但保持代码的功能不变，然后通过邮件发到LKML(Linux Kernel Mail List)里问Linus他的这种方式是不是更加合理。Linus大神刚开始还是心平气和的和跟这位新手说：合理的使用Goto可以让代码更加清晰；此外，对于使用一些不支持描述性跳转标签的语言编程时，则尽量不要使用Goto语句。接下来这位新手又回复说，他以前经常被教导”任何使用，都要使用Goto语句“之类的云云。然后Linus就开喷了，说他这样的程序员是被计算机系的教授洗脑了，实际上if-else也是一种Goto语句，for、do-while也都是变相的Goto语句。&lt;/p&gt;

&lt;p&gt;这封在Linux内核邮件讨论组的邮件最后，有一个内核的开发人员说了句话可以作为这篇博客结尾：软件开发人员不要把精力放在语言使用的宗教问题上，而应该把注意力放到Bug Fixing, New Feature Development等产品本身的问题上。&lt;/p&gt;</content><author><name></name></author><summary type="html">很多程序员可能听说过，“不要使用Goto语句”这样的观点。但是现在计算机系的学生可能很少有听到过这个原则背后有着怎么样的历史背景了。关于是否使用Goto语句、什么场合使用Goto语句曾经在编程史上引发激烈的辩论，这些争论从上个世纪的60年代一直延续到本世纪初，其中的参与者包括大名鼎鼎Dijkstra Edsger、Knuth Donald还有Linus Troald等等，大部分同学应该对这些计算机发展史上里程牌式的名字非常熟悉。以现在的眼光回去看当时这些大牛们的文章，可能会觉得这些争论已经了无意义或者类似的问题已经不复存在了，但是设身处地的回到他们各自的时代，就会看到他们的讨论对计算机编程语言演进的影响。</summary></entry><entry><title type="html">如何寻找创业点子</title><link href="http://iamyb.github.io/2013/01/06/How-to-Get-Startup-Ideas" rel="alternate" type="text/html" title="如何寻找创业点子" /><published>2013-01-06T00:00:00+00:00</published><updated>2013-01-06T00:00:00+00:00</updated><id>http://iamyb.github.io/2013/01/06/How-to-Get-Startup-Ideas</id><content type="html" xml:base="http://iamyb.github.io/2013/01/06/How-to-Get-Startup-Ideas">&lt;p&gt;&lt;em&gt;写在前面：这篇文章大部分内容是摘自硅谷创业导师PG写的&lt;a href=&quot;http://www.paulgraham.com/startupideas.html&quot; title=&quot;HOW TO GET STARTUP IDEAS&quot; target=&quot;_blank&quot;&gt;How To Get Startup Ideas&lt;/a&gt;，文章有些地方看起来不是很连贯，推荐有兴趣的同学去看原文。&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;创业不需要绞尽脑汁去找新的想法，而是寻找问题，最好是你自己经历的问题。好的创业点子通常有几个共同的特点：1）他们是创业者自己需要的；2） 创业者能够通过自己的能力实现它；3）其他人看起来觉得根本不值得一做。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;解决什么问题。&lt;/strong&gt;为什么需要你自己经历的问题呢？这样可以确保这个问题真的存在，可以确保你试图解决的是一个实际存在的问题。而目前，很多创业的项目常常试图解决一些创业者自己想象出来的问题。这是非常危险的。当你有一个创业点子的时候，问问自己：谁马上需要这个产品？谁非常需要目前产品，即使它还是由几个他没有听说过的人创造的半成品？如果你不能回答这个问题，那么直接放弃这个点子。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;挖深坑，深挖坑。&lt;/strong&gt;通常情况下，创业公司的启动项目只可能有两种选择：一种是满足大量用户非必要需求；另一种是满足少量用户的强烈需求。那种既有很多用户，用户又有强烈需求的项目一般都已经有人在做了。在这两种项目中，选择后者作为创业公司的启动项目，用中国话说就是深挖坑（深井）、广积粮、缓称王。除了深挖坑外，还有一个很重要的条件是可复制性。像Facebook早期只在哈弗大学的校园内使用，之后很快就在在全美的大学流行起来，就是很为它有很好的可复制性。微软同样也是这样的。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;武装自己。&lt;/strong&gt;让自己始终处在一个领域的前沿，“想象着生活在未来，然后创造那些需要的产品”。如果你回头看看那些改变世界的产品，Google, Yahoo，Facebook，Apple等等，都是这样的。如果你目前不在这些快速发展的领域，那怎么办呢？选择一个然后加入，任何足够聪明的程序员都能在一年内走到一个编程领域的前沿，比如移动应用程序的开发。一般来说，一个成功的创业至少需要3到5年的时候，那花一年时间学习准备应该是一项合理的投资。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Live in the future and build what missing. It’s generally the result of some external stimulus hitting a prepared mind&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;细心观察。&lt;/strong&gt;如果你正好处于一个领域的前沿，那要特别把注意力放在那些让你懊恼的事情上面，它们让你感到懊恼很有可能是因为你生活在未来。这就好像如果让你回到过去20年，你会感到生活有诸多不便和限制，而这些[不便和限制]便是过去20年到现在所改变的地方。&lt;/p&gt;

&lt;p&gt;从日常工作生活中，并没有需要刻意的去寻找这些需求，比如坐下来，然后苦思冥想什么的，这完全没有必要。重要的是当我们遇到难题的时候，要保持一颗强烈的好奇心，并且想办法把这些问题解决（此时你就相当于在某些领域的前沿，或者往领域的前沿更近了一步），然后注意是否有能改善的地方。另外就是观察身边的人的需求。&lt;/p&gt;

&lt;p&gt;一个方法可以把你放进观察需求的路上来，就是让你自己工作在那些很酷的项目上面。如果你去做的话，你很有可能就是在创造那些缺少的需求。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;不要害怕竞争。&lt;/strong&gt;如果你有一个想法，你可能会担心你是不是已经太晚了？不用担心，花几分钟在网上搜索就可以知道答案了。即使有其他人已经在做了，你现在进入可能也不会太晚。很少很少有创业公司是被它的竞争对手打败的（通常是被他们自己打败的）。假如你对这点不太确定，只要问问自己你的点子里面是否有其他人强烈需要的东西，如果有的话，那么你已经抢到滩头堡了。&lt;/p&gt;

&lt;p&gt;你也没有必要担心进入一片“红海”，只要你看到了那些目前被这片红海所忽略的东西（你必须确保你能够具体描绘出这样的东西，而不是存在你的想象中）。另外一方面，红海通常意味着市场足够大并且目前并没有足够好的解决方案。不能奢望进入一个市场很大却没有竞争对手的领域。成功的创业公司或是带着“秘密武器”踏入这些有竞争对手的领域（像google），或者想微软一样进入一个小到足够让大公司忽略的领域然后逐渐壮大。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;面对琐事和难点。&lt;/strong&gt;在你观察或寻找创业想法时，不要去忽视那些困难的事情以及琐碎的事。很多程序员想着写点看起来很酷的代码，把他们放到一个服务器上面，然后就会有用户过来乖乖的给你付钱了。只能说想法很傻很天真。现实世界中充斥着各种或简单、或复杂的琐事，面对它们极有可能会找到一些其他有价值的想法，甚至可以激发出新的创业想法。Stripe就是一个很好的例子。(Stripe是为其他开发者搭建支付系统评台提供商)&lt;/p&gt;

&lt;p&gt;总结。最好在你自己的专业领域寻找创业的点子。假如你是一个数据库专家，那么就不要想着去写一个给青少年用的聊天工具了。它可能是一个很好的想法，但是你不能相信你自己的判断，所以忽略它。在数据库领域肯定有其他的创业点子，你可以判断它们的质量。你可能也发现在数据库领域很难有好的想法，那是因为你的专业程度提高了它的标准，而在其他领域则是降低了标准。&lt;/p&gt;

&lt;p&gt;这个点子最好是去解决你自己的问题，当然你旁边其他人也可能有类似的问题，那么你可以喝你身边的人交流一下。如果你自己真的没有好的想法，那么尝试解决其他人遇到的问题。一个解决其他人问题的方法就是让自己身临其境去面对他人的问题。比如你要写一个点菜软件，那最好的办法就是先去餐馆工作几天吧。&lt;/p&gt;</content><author><name></name></author><summary type="html">写在前面：这篇文章大部分内容是摘自硅谷创业导师PG写的How To Get Startup Ideas，文章有些地方看起来不是很连贯，推荐有兴趣的同学去看原文。</summary></entry><entry><title type="html">需要什么样的代码审查方法？</title><link href="http://iamyb.github.io/2012/11/06/More-Reasonable-Code-Review-WoW" rel="alternate" type="text/html" title="需要什么样的代码审查方法？" /><published>2012-11-06T00:00:00+00:00</published><updated>2012-11-06T00:00:00+00:00</updated><id>http://iamyb.github.io/2012/11/06/More-Reasonable-Code-Review-WoW</id><content type="html" xml:base="http://iamyb.github.io/2012/11/06/More-Reasonable-Code-Review-WoW">&lt;p&gt;公司最近严控代码质量，代码审查（Code Review）相应地也就多了起来。每天常常收到好几封代码审查的邀请邮件，每封邮件都包含了需要审查的代码附件，这些附件的压缩方式还是各式各样的都有，7z, zip, rar等等，附件中还有一个用来填写评论（Comment）的Excel表格。直到上周的有一天，我公司邮箱不小心又被爆仓了，收件箱按照附件排列一看大多是代码审查相关的邮件，终于对这种工作方式受不了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/code_review.png&quot; alt=&quot;_config.yml&quot; /&gt;&lt;/p&gt;

&lt;p&gt;先说说这种目前这种代码审查的方法有都么的繁冗。每次我收到这种邮件，第一步是把附件保存到一个临时的目录，第二步是把这个附件解压缩，第三用Beyond Compare把解压缩出来经过改动的文件进行比较，第四步开始审查代码然后把评论记录到Excel里面（这其中需要填写源代码文件，代码行，评论，问题等等），第五步是把评论过发回给代码审查请求者。第六步，通过邮件和请求者对评论做进一步的交流。&lt;/p&gt;

&lt;p&gt;而请求代码审查的工程师则需要做更多的事情：第一步，需要从代码目录树中抽取改动的文件放到一个文件夹里面，第二步，把对应版本未作改动的文件放到一个文件夹，第三步，把这两个文件夹压缩然后。第四步，撰写代码审查的邀请邮件并发送给审查者。第五步，收集各种评论；第六步，对评论Reject或者Accept并通过邮件做进一步交流，第七步，改动代码并发出来重新审查，然后重复流程；最后全部流程完毕才可以提交代码。&lt;/p&gt;

&lt;p&gt;可以看到，这种代码审查的方式有很多的弊病：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;不可以被检索、跟踪和统计；有的评论全部放在Excel里面，Excel文档又放在内部的某个服务器里面；&lt;/li&gt;
  &lt;li&gt;尽可能避免评论，因为评论方式复杂，审查的软件工程师不是那么重要的问题就直接忽略；&lt;/li&gt;
  &lt;li&gt;跳过代码审查，软件工程师可能因为流程繁冗，直接跳过代码审查而把新改动的代码提交到代码库里面；&lt;/li&gt;
  &lt;li&gt;审查效率低下，从代码审查请求发起到代码审查一直不断陷入操作和流程，蚕食着工程师代码审查时间和精力；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这是一种小作坊式的代码审查方法，比较专业的说法是Mail Pass Code Review。而目前大的软件公司和项目更多地采用的是协同式的代码审查工具，比如大名鼎鼎的开源工具Review Board以及商业软件Crucible，使用这些工具的好处显而易见。在我受不了的那一天，我把Review Board安装到本地的虚拟机上，然后尝试用这个工具来审查最近改动的代码，顿时觉得精神气爽。&lt;/p&gt;

&lt;p&gt;在使用Review Board的过程中，上诉代码审查的弊病完全都可以避免。它还可以和代码库集成在一起，自动的生成改动代码的diff文件，可以在浏览器端直接在diff文件内置评论；可以针对每个评论提一个问题，只有问题被解决才可以把这个问题关掉；可以在浏览器端跟踪所有代码审查请求的状态，最重要的是它跟代码库集成在一起之后，可以让工程师的每次代码提交（commit）强制执行代码审查，从而提高代码质量。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CEO一再声称，让公司成为Software Driven的科技公司，从目前代码审查的工具使用这点来看，道阻且长。&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;附录：&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://alephnullplex.appspot.com/blog/view/2009/07/09/tutorial-installing-review-board-on-ubuntu&quot;&gt;Install Review Board on Unbuntu&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.reviewboard.org/docs/manual/dev/users/&quot;&gt;Review Board User Guide &lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.methodsandtools.com/archive/archive.php?id=66&quot;&gt;Four Ways to a Practical Code Review&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</content><author><name></name></author><summary type="html">公司最近严控代码质量，代码审查（Code Review）相应地也就多了起来。每天常常收到好几封代码审查的邀请邮件，每封邮件都包含了需要审查的代码附件，这些附件的压缩方式还是各式各样的都有，7z, zip, rar等等，附件中还有一个用来填写评论（Comment）的Excel表格。直到上周的有一天，我公司邮箱不小心又被爆仓了，收件箱按照附件排列一看大多是代码审查相关的邮件，终于对这种工作方式受不了。</summary></entry><entry><title type="html">奇特的一生</title><link href="http://iamyb.github.io/2012/08/19/This-is-Strange-Life" rel="alternate" type="text/html" title="奇特的一生" /><published>2012-08-19T00:00:00+00:00</published><updated>2012-08-19T00:00:00+00:00</updated><id>http://iamyb.github.io/2012/08/19/This-is-Strange-Life</id><content type="html" xml:base="http://iamyb.github.io/2012/08/19/This-is-Strange-Life">&lt;p&gt;奇特的一生讲述了苏联昆虫学家亚历山大•柳比歇夫[1]的故事。柳比歇夫一生成就非凡，不仅能够在自己的昆虫学专业领域取得很大的成就，而且在其他诸如宗教、哲学、历史等领域令其专业学者侧目。因此引发作者思考的事：柳比歇夫的一生能够干那么多事情、留下那么多的作品，而同一时代的大部分人则碌碌无为的离开人世，为什么会这样呢？于是作者在柳比歇夫的诸多资料中看到了他奇特的时间统计法（用现在比较流行的话说就是时间管理）。&lt;/p&gt;

&lt;p&gt;柳比歇夫的这种方法到底有什么奇特之处值得大写特写？初看这种奇特的时间统计法非常的普通——无非就是把每天的每个时刻每一笔时间支出都详细记录在日记中，在其他人看来甚至很是枯燥——连走路15分钟都要记录下来！然而，书中认为他的时间统计法的关键在于阶段性的统计。统计的阶段性可以是每周统计、每月统计、每年统计、每5年统计等等；而统计又可按深度广度分为横向的统计及纵向的统计。例如对于柳比歇夫来说，横向的统计可以使他用于人生使命的昆虫分类学、自我学习需要的伦理学宗教学历史等、以及个体生活需要（娱乐、锻炼、睡觉、吃饭、陪老婆孩子等）的各项时间支出。这对一个人的一生来说，确实是一项浩大至伟的工程！&lt;/p&gt;

&lt;p&gt;在作者看来，这也是其他一些伟大人物所具有的品行——分类统计归纳，书中专门列了一个章节来讲述那些伟大学者的一些特性，特别提到门捷列耶夫的纪念馆——“……一捆捆妈好的劈柴仍旧堆在前廓、过道和房间里，堆在炉子波纹状的铁支架后面……”，无不凄凉地感叹——“我们曾经这样生活来着。我们的父母也曾经这样生活来着。”，只是流年暗转，那些普通人在历史车轮滚滚中灰飞烟灭，只留那些伟大的灵魂在他们的遗物中延续生命。当然，柳比歇夫的生活对于大部分普通人来说是过于理性，甚至有些人觉得这种做法会限制自身的自由（什么是自由？）。书中也试图从另一个角度给出一种解释——这么做只是需不需要的问题。&lt;/p&gt;

&lt;p&gt;书中除主线之外提出的一些东西，{从柳比歇夫的书信中对自己的剖析中看到柳比歇夫的精神标准，如乐天、话唠、反派、好心等等。又引出了精神标准和科学标准的重要性评判——每当科学与精神品质发生冲突，我首先关心的精神品质&amp;amp;人的精华中，最值得称道、最牢固的，是精神价值。然后又从柳比歇夫与友人的通信中看到了其爱好的广泛、修养的深度，将其对知识与真理的渴望及批判——他认为他是虚无主义者，屠格涅夫所说的那种虚无主义者。作者最后感叹，随着这一代人的逝去，本世纪初和十月革命时代的俄罗斯文化即将成为明日黄花、过眼烟云。}&lt;/p&gt;

&lt;p&gt;【摘录】
[1] 我们好象只能使用经过精选的时间。我们记得的只是一生中最精彩的时刻。半个小时对我们来说不算时间。我们只承认整段整段的时间，只承认不受客观环境和偶然事件干扰的大段时间。只有在这样的时间里，我们才打算大显身手。短一点的时间，我们马上会借口外界干扰、借口客观条件而认为不适用。啊，不依我们意志为转移的客观条件，具有充分权力和理由的客观条件真是威力无比！把责任往它们身上互推，那是多么轻而易举啊……&lt;/p&gt;

&lt;p&gt;[2] 我们的记忆是靠什么？靠事件。我们的生活是拿事件来做标志的。它们仿佛是路标，路标之间却是一片空白……比方说，我自从写柳比歇夫的小说以来，最近这几个月的时光都跑到哪儿去了？伏案写作的时间本身并不多，这些日子都干什么了？我可是干事儿来着，一直忙得很；究竟忙些什么，却记不起来。是瞎忙还是忙的正事——这九十天该怎么总结呢？光这几个月倒也罢了……以往，年轻的时候，每逢过年，我总猛然想起，一年又过去了，我决心要做的，并且也向别人保证了的，又没有做成——一部小说没有写完，诺沃戈罗奇纳没有去成，有些信没有回复，同谁没有见成面，又是什么没有做……拖啊拖，结果是无可再拖了。&lt;/p&gt;

&lt;p&gt;[3] 既然是这样，那么一切关于人是机器的论调还有什么意义呢！到底我们怕什么呢？我想，是怕给自己规定纪律。当然罗，没有这个时间统计法生活更轻松一些，就象一般说来某个阶段不学习会更轻松；不提高自己，不为别人做事也更轻松。但是，如果不去考虑轻松不轻松的问题，而考虑需要不需要的问题，那么人必然会严肃地考虑如何利用他一天、一月、一年中荒废排的那些时间。假如能把一个人在生产中、生活中花费掉的时间摆出来给他看，他一定会发现他白白地、糊里糊涂地浪费掉的那一部分生命而大吃一惊。&lt;/p&gt;

&lt;p&gt;[4] 德漠克利特有句话：决定人的精神品质的，不是他的行为本身，而是他的意图。&lt;/p&gt;

&lt;p&gt;[5] 在他紧张的精神生活中，他崇敬的英雄们、他喜爱的人儿、他的表率都不断在变换。仔细去考察这种变化，该是很有意思的事。对于柳比歇夫，任何时候都不能说他已“成为”怎样一个人。他永远正在“逐步成为”怎样一个人。他一直在探索，一直在变化，他总是重新考虑，不断提高对自己和对自己理想的要求。&lt;/p&gt;

&lt;p&gt;【参考】
[1] Alexander Alexandrovich Lyubishchev
&lt;a href=&quot;http://www.zin.ru/animalia/coleoptera/eng/lyubishc.htm&quot;&gt;http://www.zin.ru/animalia/coleoptera/eng/lyubishc.htm&lt;/a&gt;&lt;/p&gt;</content><author><name></name></author><summary type="html">奇特的一生讲述了苏联昆虫学家亚历山大•柳比歇夫[1]的故事。柳比歇夫一生成就非凡，不仅能够在自己的昆虫学专业领域取得很大的成就，而且在其他诸如宗教、哲学、历史等领域令其专业学者侧目。因此引发作者思考的事：柳比歇夫的一生能够干那么多事情、留下那么多的作品，而同一时代的大部分人则碌碌无为的离开人世，为什么会这样呢？于是作者在柳比歇夫的诸多资料中看到了他奇特的时间统计法（用现在比较流行的话说就是时间管理）。</summary></entry></feed>