使用應用程式跟蹤對效能改變進行量化分析(轉)

amyz發表於2007-08-10
使用應用程式跟蹤對效能改變進行量化分析(轉)[@more@]

  使用 Apache Web 伺服器作為示例,以瞭解如何分析公共配置的效能含義。使用應用程式跟蹤來觀察應用程式執行過程中進行的系統呼叫。透過統計呼叫的次數和發生的時間,您可以輕鬆地瞭解效能改變的影響。

  您可以對應用程式進行跟蹤,以找出它們暫停或不執行的原因。並且可以使用同樣的方法,瞭解更多關於應用程式的資訊並理解某些配置的效能含義。因為 Apache 非常流行並且大多數讀者對它都比較熟悉,所以本文使用 Apache 作為示例。Apache 所進行的每次系統呼叫都會對 Web 頁面的提供帶來延遲,透過跟蹤不同配置下的 Web 伺服器,您可以確定具體配置的影響。

  應用程式跟蹤概述

  在應用程式的執行過程中,當需要開啟檔案、傳送資料包或者使用系統資源時,它會對基礎作業系統進行相應的系統呼叫。跟蹤應用程式意味著可以在呼叫發生時觀察到這些系統呼叫,這將使得您能夠深入地瞭解該應用程式的行為。在 Solaris 和 IBM AIX® 作業系統 (AIX) 中,使用 truss 命令完成這項任務,而在 Linux® 中則使用 strace。清單 1 顯示了對 pwd 命令進行跟蹤的示例。

  清單 1. 跟蹤 pwd 命令

  -bash-3.00$ truss pwd

...

getcwd("/export/home/sean", 1025)        = 0

/export/home/sean

write(1, " / e x p o r t / h o m e".., 18)   = 18

_exit(0)

  在刪除開始處與載入該應用程式相關的輸出內容後,您可以看到所進行的三次系統呼叫:

  1. getcwd 返回當前工作目錄。輸出內容中顯示了字串“/export/home/sean”返回到緩衝區。
  2. write 可以顯示給定的字串。因為在其執行之後才顯示這個系統呼叫,所以先輸出了它的執行結果。還可以注意到,write 系統呼叫的結果是寫入字元的個數數目,在這個示例中為 17 加上一個回車。
  3. _exit 使用錯誤程式碼 0 退出該程式,這個錯誤程式碼通常表示成功結束。

  儘管這是一個很簡單的示例,但它演示了透過應用程式跟蹤可以觀察程式內部機制的程度。有關跟蹤方面更深入的資訊,請參見參考資料部分。

  Apache 配置的簡要介紹

  可以透過一個名為 httpd.conf 的檔案對 Apache Web 伺服器進行配置。清單 2 顯示了一個簡單配置中的部分內容。

  清單 2. 示例 httpd.conf

  DocumentRoot "/var/apache/htdocs"

  Options FollowSymLinks

  AllowOverride None

  Options Indexes FollowSymLinks MultiViews

  第一行定義了在何處可以找到 HTML 檔案。將所有的請求都對映到這個目錄。如果請求 /project/charter.html,將使用 /var/apache/htdocs/project/charter.html 提供該頁面。httpd.conf 中剩餘的部分由兩個 Directory 節組成。 之間的任何內容都將應用於指定目錄及其所有的子目錄。在本例中,第一節將兩項設定應用於根目錄,而第二節則指向 /var/apache/htdocs。

  如果多個節應用於單個請求,那麼將會對這些命令進行組合,並且最適合的目錄具有高優先順序。例如,將使用 /var/apache/htdocs/project/charter.html 提供 /project/charter.html 請求的頁面。/var/apache/htdocs 是 / 的子目錄,所以 Options Indexes FollowSymLinks MultiViews 來自第二節,AllowOverride None 來自第一節。

  可以對許多內容進行配置,並且每項內容都具有其效能含義。本文餘下的內容重點關注於如何對這些改變的影響進行量化分析。

  建立基準

  在您進行任何調整之前,務必要了解系統當前的執行方式。使用 -X 引數啟動 Apache,這個引數將強制 Apache 進入單程式除錯模式。這樣做可以確保將請求傳送到正在進行跟蹤的程式,並且消除常規程式間通訊所帶來的開銷。

  在守護程式啟動之後,透過執行 ps -ef 找到相應的程式 ID,並查詢 httpd 守護程式。在找到該程式之後,使用 truss -c -p PID 附加到該程式。-c 選項表示對系統呼叫進行計數,而不是逐個顯示它們,而 -p 則表示將跟蹤器附加於一個正在執行的程式。

  使用 Web 瀏覽器請求文件。在頁面載入之後,回到 truss 應用程式,然後按 Ctrl-C 以結束計數。對於靜態 HTML 頁面,您應該看到如清單 3 所示的內容(為使這些數字變得更有趣,本示例進行了 100 次相同的請求)。

  清單 3. 系統呼叫基準

  sunbox# truss -c -p 15026

(make the Web request 100 times)

^C

syscall        seconds  calls errors

read           .009   200

write          .020   200

close          .020   200

time           .004   300

alarm          .018  1100

fcntl          .009   300

sigaction        .007   400

munmap          .007   100

llseek          .001   100

pollsys         .005   100

mmap64          .008   100

stat64          .007   100

open64          .006   100

accept          .019   100

getsockname       .002   100

setsockopt        .002   100

           -------- ------  ----

sys totals:       .149  3600   0

usr time:        .120

elapsed:        8.960

  truss 返回系統呼叫的列表、執行呼叫耗費的總時間、呼叫的次數和任何發現的問題。在這個報表的結尾處,返回了這些系統呼叫耗費的總時間,以及執行應用程式所耗費的時間。對於這些目的來說,所耗時間是沒有意義的,因為它指的是從啟動 truss 開始到其結束的時間,而與 Web 請求沒有任何關係。

  清單 3 顯示了最簡單的情況。在來自 Web 瀏覽器的連線請求到達後,accept 系統呼叫完成該連線。Web 伺服器使用 read 呼叫獲得請求的內容,將請求的內容對映到磁碟上的檔案。Web 伺服器首先使用 stat64 驗證該檔案是否存在,使用 open64 開啟該檔案以便進行讀取,然後使用 mmap64 將該檔案的內容對映到記憶體中。然後使用 write 將這個檔案傳送回客戶端,使用另一個 write 生成日誌檔案,並且伺服器執行來自瀏覽器的最後一個 read。該列表中其餘的呼叫都是系統開銷,並且當配置發生改變時,不會有顯著的變化。

  解釋這些數值

  100 次請求總共耗費 0.269 秒 (0.149 + 0.120),這樣的效能相當不錯,並且該伺服器每秒鐘應該可以提供大約 370 個頁面 (100/0.269)。但是不能完全相信這些數值,因為它們僅表示程式耗費在 CPU 上的時間,而不是其真正的執行時間(也稱為時鐘時間)。還有更多的因素需要考慮,如磁碟和網路的速度、計算機上正執行的其他內容、該守護程式執行於除錯模式的事實。您還需要考慮系統呼叫跟蹤本身的開銷。

  本文中使用的方法重點關注這些操作的相對計時和使用應用程式跟蹤消除浪費掉的操作。如果您需要了解 Web 伺服器每秒可以提供的頁面數目,參考資料部分中有相應的軟體連結,它可以幫助您確定該數值。

  跟蹤 AllowOverride 範圍

  Apache 允許管理員透過 .htaccess 機制將配置權委託給個別的使用者。.htaccess 是一個包含附加配置指令的檔案,如果在 httpd.conf 中透過 AllowOverride 配置了請求的目錄,那麼 Web 伺服器將搜尋這個檔案。清單 4 顯示了前面的配置了 AllowOverride Limit 的配置資訊,它允許使用者獲取訪問 Web 頁面的使用者名稱和密碼。

  清單 4. 配置了 AllowOverride 的示例 httpd.conf

  DocumentRoot "/var/apache/htdocs"

  Options FollowSymLinks

  AllowOverride Limit

  Options Indexes FollowSymLinks MultiViews

  重新啟動 httpd 守護程式並再次執行這些測試,其結果如清單 5 所示。

  清單 5. 開啟了 AllowOverride Limit 的 100 次請求的結果

  sunbox# truss -c -t write,read,open64,stat64,mmap64 -p 21136

^C

syscall        seconds  calls errors

read           .012   200

write          .021   200

mmap64          .007   100

stat64          .007   100

open64          .022   500   400

           -------- ------  ----

sys totals:       .072  1100  400

usr time:        .141

elapsed:        16.660

  初看起來,系統呼叫耗費的時間下降了,但這是因為使用了 -t 選項將跟蹤任務限制於一些有意義的系統呼叫。大多數系統呼叫並沒有發生變化,但現在有 500 次 open64 呼叫,其中有 400 次返回了錯誤。執行 open64 的時間增加了(從 0.006 秒增加到 0.22 秒),同時使用者空間部分的時間也增加了(從 0.12 秒增加到 0.141 秒)。

  時間增加是因為 Apache 現在必須完成附加的工作以處理該請求,即使沒有配置重寫。單獨的 AllowOverride Limit 配置明顯地增加了開銷。問題依然存在,即什麼導致了這些錯誤? 要回答這個問題,可以跟蹤單個 Web 請求,如清單 6 所示。

  清單 6. 確定 open64 呼叫失敗的原因

  sunbox# truss -t open64 -p 21136

open64("/.htaccess", O_RDONLY)         Err#2 ENOENT

open64("/var/.htaccess", O_RDONLY)       Err#2 ENOENT

open64("/var/apache/.htaccess", O_RDONLY)    Err#2 ENOENT

open64("/var/apache/htdocs/.htaccess", O_RDONLY) Err#2 ENOENT

open64("/var/apache/htdocs/test.html", O_RDONLY) = 5

  清單 6 顯示了當請求進入時,Apache 對每個指向 /var/apache/htdocs 的目錄進行檢查並嘗試開啟 .htaccess 檔案,但是因為 AllowOverride 配置為根目錄,所以這個檔案並不存在。Apache 必須在每個子目錄中查詢 .htaccess 檔案的重寫資訊,並對它們進行處理。這樣一來,由於額外的系統呼叫、更多的使用者空間開銷和額外的磁碟活動,從而進一步增加了延遲。對於 100 次請求來說,增加零點幾秒的時間看起來並不是很明顯,但是對於一臺繁忙的伺服器,就會增加更長的延遲。

  既然您瞭解了重寫的範圍,那麼理想的解決方案是不允許重寫,並且強制在 httpd.conf 中對所有的內容進行配置。如果失敗,可以將配置的範圍限制於需要它的目錄。在這個研究示例中,把 AllowOverride Limit 放到第二個 Directory 節中,這將僅新增一個額外的 open64 呼叫,以便在 /var/apache/htdocs 中查詢 .htaccess。對所有的父目錄進行搜尋是浪費時間,因為在這個配置中,不會使用其中的任何檔案來提供頁面。

  研究主機名查詢

  當 Web 伺服器接收到一個請求時,它所知道的關於客戶端的資訊只有其 IP 地址,如 129.42.42.212 對應於 IBM.com。然而,Web 伺服器並不知道這個地址來自於 IBM.com,因此,它必須進行反向 DNS 查詢。這樣做需要耗費一定的時間,如果在傳送請求之前需要這個名稱,那麼將會延遲對客戶端的響應。過去,Apache 在預設情況下會執行這些反向查詢,但現在這種行為已經有了改變。

  還有另一種情況,其中必須進行反向 DNS 搜尋。當基於主機名(而不是 IP 地址)配置訪問限制時,Apache 必須首先將 IP 地址反向解析為相應的主機名,然後再次將主機名解析為 IP 地址,以確保它們正確匹配。因為反向域名搜尋可以由地址塊所有者確定,所以要防止 IP 欺騙的發生,必須進行第二次查詢。可以透過應用程式跟蹤來確定 DNS 解析的影響嗎?

  要對其進行測試,可以從前面的示例中刪除 AllowOverride Limit,然後新增 Allow from ibm.com 代替預設的 Allow from all。然後,對 DNS 伺服器進行更改以便向您的工作站返回 something.ibm.com,確保初始反向檢查能夠成功並且隨後的正向查詢必須透過 Internet 完成。在示例執行過程中,對保護的 Web 伺服器的請求耗費了 15 秒的時間。相反,使用 IP 地址代替 ibm.com 所耗費的時間小於半秒鐘。清單 7 顯示了在使用 DNS 確保安全時,對一些系統呼叫進行統計。

  清單 7. 透過主機名進行限制的 Web 請求的 truss 輸出

  bash-3.00# truss -c -p 26089

^C

syscall        seconds  calls errors

read           .000    5

write          .000    3

open           .000    2

close          .001   10

time           .000    3

stat           .000    5

alarm          .000    8

fcntl          .000    7    2

sigaction        .000    3

sysconfig        .000    5

pollsys         .001    5

door_info        .000    2

stat64          .000    1

open64          .000    2

so_socket        .001    5

accept          .000    1

connect         .002    5

recvfrom         .000    2

send           .001    5

getsockname       .000    1

setsockopt        .000    1

           -------- ------  ----

sys totals:       .011   81   2

usr time:        .004

  truss 報告了該程式所耗費的時間遠遠小於客戶端感覺到的時間(0.015 秒與 15 秒)。這是因為大多數套接字操作都是非同步地 進行的,其中套接字進行輪詢以檢查資料是否出現,而不是使得應用程式處於阻塞(等待)狀態以等待響應。如此一來,應用程式在等待結果的時候不會消耗 CPU 時間。這就解釋了 truss 報告的時間和客戶端感覺到的時間之間出現差異的原因。

  truss 並沒有忘記所做的更改,0.015 秒比本文中研究的第一個簡單示例要高一個數量級。從系統呼叫計數中可以看出,有一些以前沒有出現過的呼叫,包括 read、write、close 和 stat。以及還有 send、connect、so_socket 和 pollsys,這些系統呼叫用於進行名稱請求。因為名稱解析可以來自於不同的來源,包括本地檔案系統和名稱快取守護程式,所以必須對這幾個位置進行檢查。在隨後的呼叫中,請求時間小於 1 秒,這是因為對 DNS 資訊進行了快取。

  最後,大部分的延遲來自於遠端名稱伺服器和正向解析。這個事實進一步強調了,如果您希望依賴於名稱查詢,那麼就需要使用 DNS 快取和快速 DNS 伺服器。然而,最佳的解決方案是使用一種可選的方法來處理這個問題。一種比較簡單的解決方案是指定 IP 地址塊(如 Allow from 10.0.0.0/8),這種方法比 DNS 查詢要快得多。因為反向和正向查詢必須匹配,所以對名稱進行的操作,很可能可以用於網段。另外,Apache 可以整合各種身份驗證系統,所以基於使用者的身份驗證是另一種可選方法。

  系統呼叫與庫呼叫

  如果熟悉套接字程式設計,那麼您可能會尋找 gethostbyname 和其他類似的呼叫,這些呼叫都可以用來執行主機查詢功能。有一些庫呼叫,由 /usr/lib 中的系統庫 libc 和 libsocket 提供。庫呼叫封裝了一個或多個系統呼叫,以及額外的邏輯。您可以將它們作為程式設計師友好的介面來進行系統呼叫。例如,gethostbyname 庫呼叫將執行許多步驟,以便根據伺服器的配置查詢相應的名稱,如檢查 /etc/hosts 或搜尋網路資訊系統 (NIS) 或 DNS。這些步驟包含了核心所提供的更小的構件,即系統呼叫。在大多數這樣的這種情況下,兩者之間的差別通常很小。truss 還可以跟蹤庫呼叫,但是無法提供像系統呼叫那樣詳細的資訊。

  結束語

  監視和統計系統呼叫的功能不僅有助於進行故障排除,還有助於理解應用程式配置如何對效能產生影響。與系統的其他部分之間的每個互動操作都會呼叫一個或多個系統呼叫,並且每次呼叫都會增加系統開銷。這並不是說系統呼叫非常糟糕,如果程式設計師不與其他的部分進行互動,那將是很乏味的。相反,在改變應用程式時,您可以監視系統呼叫的使用,以便更好地瞭解這些改變對總體效能的影響。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-941673/,如需轉載,請註明出處,否則將追究法律責任。

相關文章