線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1018
推到 Plurk!
推到 Facebook!

扼殺IIS伺服器性能的十條戒律

 
conundrum
尊榮會員


發表:893
回覆:1272
積分:643
註冊:2004-01-06

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-01-25 23:04:29 IP:61.64.xxx.xxx 未訂閱
http://www.softhouse.com.cn/docs/southpark1193.html 扼殺IIS伺服器性能的十條戒律 From: Microsoft 下面的每一條戒律都將有效地影響代碼的性能和可伸縮性。換句話說,盡可能不要照著戒律去做!下面,我將解釋如何破壞他們以便提高性能和可伸縮性。 1、應該分配和釋放多個物件 你應該儘量避免過量分配記憶體,因爲記憶體分配可能是代價高昂的。釋放記憶體塊可能更昂貴,因爲大多數分配算符總是企圖連接臨近的已釋放的記憶體塊成爲更大的塊。直到Windows NT? 4.0 service pack 4.0,在多線程處理中,系統堆通常都運行得很糟。堆被一個全局鎖保護,並且在多處理器系統上是不可擴展的。 2.不應該考慮使用處理器快取記憶體 大多數人都知道由虛擬記憶體子系統導致的hard 頁錯誤代價很高,最好避免。但是許多人認爲其他記憶體訪問方法沒有什麽區別。自從80486以後,這一觀點就不對了。現代的CPUs比RAM要快得多,RAM至少需要兩級記憶體緩存 ,高速L1 緩存能保存8KB資料和8KB指令,而較慢的L2 緩存能保存幾百KB的資料和代碼,這些資料和代碼混合在一起。L1 緩存中記憶體區域的一個引用需要一個時鐘周期,L2 緩存的引用需要4到7個時鐘周期,而主記憶體的引用需要許多個處理器時鐘周期。後一數位不久將會超過100個時鐘周期。在許多方面,緩存像一個小型的,高速的,虛擬記憶體系統。 至於和緩存有關的基本記憶體單元不是位元組而是緩存列。Pentium 緩存列有32個位元組寬。Alpha 緩存列有64個位元組寬。這意味著在L1 緩存中只有512個slot給代碼和資料。如果多個資料一起使用(時間位置)而並不存儲在一起(空間位置),性能會很差。陣列的空間位置很好,而相互連接的列表和其他基於指標的資料結構的位置往往很差。 把資料打包到同一個緩存列中通常會有利於提高性能,但是它也會破壞多處理器系統的性能。記憶體子系統很難協調處理器間的緩存。如果一個被所有處理器使用的唯讀資料,和一個由一個處理器使用並頻繁更新的資料共用一個緩存 列,那麽緩存將會花費很長時間更新這個緩存列的拷貝。這個Ping-Pong高速遊戲通常被稱爲"緩存 sloshing"。如果唯讀資料在一個不同的緩存 列中,就可以避免sloshing。 對代碼進行空間優化比進行速度優化效率更高。代碼越少,代碼所占的頁也越少,這樣需要的運行設置和産生的頁錯誤也會更少,同時佔據的緩存 列也會更少。然而,某些核心函數應該進行速度優化。可以利用profiler去識別這些函數。 3.決不要緩存頻繁使用的資料。 軟體緩存可以被各種應用程式使用。當一個計算代價很高時,你會保存結果的一個拷貝。這是一個典型的時空折中方法:犧牲一些存儲空間以節省時間。如果做得好,這種方法可能非常有效。 你必須正確地進行緩存。如果緩存了錯誤資料,就會浪費存儲空間。如果緩存得太多,其他操作可以使用的記憶體將會很少。如果緩存得太少,效率又會很低,因爲你必須重新計算被緩存 遺漏的資料。如果將時間敏感資料緩存得時間過長,這些資料將會過時。一般,伺服器更關心的是速度而不是空間,所以他們要比桌面系統進行更多的緩存。一定要定期去除不用的緩存,否則將會有運行設置問題。 4.應該創建多個線程,越多越好。 調整伺服器中起作用的線程數目是很重要的。如果線程是I/O-bound的,將會花費很多時間用來等待I/O的完成-一個被阻塞的線程就是一個不做任何有用工作的線程。加入額外的線程可以增加通量,但是加入過多的線程將會降低伺服器的性能,因爲上下文交換將會成爲一個重大的overhead。上下文交換速度應該低的原因有三個:上下文交換是單純的overhead,對應用程式的工作沒有任何益處;上下文交換用盡了寶貴的時鐘周期;最糟的是,上下文交換將處理器的緩存填滿了沒用的資料,替換這些資料是代價高昂的。 有很多事情是依靠你的線程化結構的。每個用戶端一個線程是絕對不合適的。因爲對於大量用戶端,它的擴展性不好。上下文交換變得難以忍受,Windows NT用盡了資源。線程池模型會工作得更好,在這種方法中一個工人線程池將處理一條請求列,因爲Windows 2000提供了相應的APIs,如QueueUserWorkItem。 5.應該對資料結構使用全局鎖 使資料線程安全的最簡單方法是把它套上一把大鎖。爲簡單起見,所有的東西都用同一把鎖。這種方法會有一個問題:序列化。爲了得到鎖,每一個要處理資料的線程都必須排隊等候。如果線程被一把鎖阻塞,它沒有在做任何有用的事。當伺服器的負載較輕時,這個問題並不常見,因爲一次可能只有一個線程需要鎖。在負載很重的情況下,對鎖的激烈爭奪可能就會成爲一個大問題。 設想在多車道高速公路上發生了一個意外事故,這條高速公路上的所有車輛都被轉向一條狹窄的道路。如果車輛很少,這一轉換對交通流的速率的影響可以忽略。如果車輛很多,當車輛慢慢並入那條單通道時,交通阻塞會延伸幾英里。 有幾種技術能夠減少鎖競爭。 · 不要過分保護,也就是說,不是非常必要不要鎖住資料。只有需要時才去持有鎖,而且時間不要過長。不要在大段代碼周圍或頻繁執行的代碼中沒必要地使用鎖,這一點很重要。 · 對資料進行分割,使它能夠用一套獨立的鎖保護。例如,一個符號表可以按識別字的第一個字母分割,這樣在修改名字以Q開頭的符號的值時,就不會去讀名字以H開頭的符號的值。 · 使用APIs的Interlocked 系列(InterlockedIncrement,InterlockedCompareExchangePointer等)自動修改資料而不需要鎖。 · 當資料不是經常被修改時可以使用多讀者/單作者(multi-reader/single-writer)鎖。你將獲得更好的並發性,儘管鎖操作的代價將更高並且你可能會冒餓死作者的危險。 · 在關鍵部分使用迴圈計數器。參見Windows NT 4.0 service pack 3中的SetCriticalSectionSpinCount API。 · 如果你不能得到鎖,使用TryEnterCriticalSection並做一些其他的有用的工作。 高競爭導致serialization,serialization導致降低CPU的利用率,這促使用戶加入更多的線程,結果事情變得更糟。 6.不必注意多處理器機器 你的代碼在多處理器系統上比在單處理器系統上運行得還要糟,這可能是件令人噁心的事。一個很自然的想法是,在一個N維系統上運行N次會更好。性能很差的原因是競爭:鎖競爭,匯流排競爭,和/或緩存列競爭。處理器都在是爭奪共用資源的所有權,而不是做更多的工作。 如果你一定要編寫多線程應用程式的話,你應該在多處理器盒上對你的應用程式進行強度測試和性能測試。單處理器系統通過時間分片地執行線程而提供一個並發性的假像。多處理器盒具有真正的並發性,競爭環境和競爭更容易發生。 7.應該始終使用模組化調用;他們很有趣。 利用同步模組化調用來執行I/O操作對大多數桌面應用程式來說是合適的。但是,他們不是使用伺服器上的CPU(s)的好方法。I/O操作要花費上百萬個時鐘周期來完成,這些時鐘周期本來可以被更好地利用。利用非同步I/O你能得到顯著提高的用戶請求率和I/O通量,不過增加了額外的複雜性。 如果你有需要花費很長時間的模組化調用或I/O操作,你應該考調撥多少資源給他們。你想使用所有的線程還是有個限制?一般地,使用有限的幾個線程要好些。構建一個小的線程池和佇列,利用佇列來安排線程的工作完成模組化調用。這樣,其他線程就可以拾取和處理你的非模組化的請求。 8.不要進行測量 當你能夠測量你所談論的事情並用數位表達它時,這就表示你對他有了一定的瞭解;但是如果你不能用數位表達時,你的知識是貧瘠的不能令人滿意的;這可能是知識的開始,但這時你簡直不可能將你的思想提高到科學的水平。 - Lord Kelvin (William Thomson) 如果不測量你就不能瞭解應用程式的特性。你在黑暗中摸索,一半是靠猜測。如果不識別性能問題,你就不能做任何改進或做出工作量計劃。 測量包括黑匣子測量和profiling。黑匣子測量的意思是收集由性能計數器(記憶體使用,上下文交換,CPU利用等)和外部檢測工具(通量,反映時間等)所顯示的資料。爲了profile你的代碼,你編譯代碼的一個工具版,然後在各種條件下運行它,並收集關於執行時間和程序呼叫頻率的統計資料。 測量如果不用於分析的話就一點用都沒有。測量將不僅告訴你有問題,而且甚至能幫助你找到問題發生在哪,但它不能告訴你爲什麽會有問題。對問題進行分析以便你能正確地改正他們。要從根本上解決問題而不是停留在表面現象。 當你進行改動後,要重新測量。你要知道你的改動是否有效。改動也可能會暴露其他性能問題,測量-分析-改正-再測量的迴圈就會重新開始。你也必須要有規律地進行測量,以便發現性能衰退問題。 9.應該使用單一用戶,單一請求的測試方法。 書寫ASP和ISAPI應用程式的一個通病是只用一個瀏覽器去測試應用程式。當他們在Internet上應用他們的程式時,他們才發現他們的應用程式不能處理高負載,並且通量和反應時間另人可憐。 用一個瀏覽器測試是必要的但是不夠的。如果瀏覽器反應得不夠快,你就知道你有麻煩了。但即使它在使用一個瀏覽器時很快,你也不知道它處理負載的能力如何。如果十幾個用戶同時請求會發生什麽事?一百個呢?你的應用程式能容忍什麽樣的通量?它能提供什麽樣的反應時間?在輕載時這些數位會怎樣?中等負載呢?重載呢?在多處理器機器上你的應用程式會如何?對你的應用程式進行強度測試,這對於找出bugs發現性能問題來說是基本的。 類似的負載測試考慮適用於所有的伺服器應用程式。 10.不應使用實際環境。 人們往往只在幾個特定的,人工的環境(如下benchmarks)下調整應用程式。選擇和實際情況相對應的各種情況,並爲針對各種操作進行優化,這一點很重要。如果你不這樣做,你的用戶和評論家一定會這樣做,並且他們將依此來評判你的應用程式的好壞。
系統時間:2024-05-06 19:39:30
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!