在構建HTTP Web服務器的上下文中......我們理解,理論上,爲每個請求創建和銷燬線程相對昂貴,並且不能很好地擴展。這是常識(或者我希望是這樣)。線程池是這裏的解決方案......但我有點想在低層理解事情,而不是簡單地接受理論爲真。如何配置線程生命週期性能
當然,我們才能用JMeter看到一個應用程序可能如何負載下運行進行黑箱測試,但如果我想實際觀察爲什麼會發生什麼? Profiler工具可以告訴我爲什麼線程分配每個請求的成本高昂嗎?
謝謝!
在構建HTTP Web服務器的上下文中......我們理解,理論上,爲每個請求創建和銷燬線程相對昂貴,並且不能很好地擴展。這是常識(或者我希望是這樣)。線程池是這裏的解決方案......但我有點想在低層理解事情,而不是簡單地接受理論爲真。如何配置線程生命週期性能
當然,我們才能用JMeter看到一個應用程序可能如何負載下運行進行黑箱測試,但如果我想實際觀察爲什麼會發生什麼? Profiler工具可以告訴我爲什麼線程分配每個請求的成本高昂嗎?
謝謝!
如果你想自己測量,你可以這樣做。
當這種智慧被發現時,很可能很久以前,創建線程要貴得多。例如在Linux上,每個線程都是一個新進程。
「昂貴」對不同的應用程序意味着不同的東西。如果系統中的每個請求都需要很長時間,那麼添加毫秒就不會有太大的區別。如果每個請求都需要幾毫秒,那麼爲啓動線程添加一個毫秒就非常糟糕。
import java.util.ArrayList;
import java.util.List;
public class ThreadRestarterMain {
public static void main(String... ignored) throws InterruptedException {
long start = System.currentTimeMillis();
// time how long it takes to start a few threads and stop them again.
int threads = 2000;
List<Thread> threadList = new ArrayList<>();
while (threadList.size() < threads) {
Thread e = new Thread(new Runnable() {
@Override
public void run() {
Thread.yield();
}
});
e.start();
threadList.add(e);
}
for (Thread thread : threadList) {
thread.join();
}
long time = System.currentTimeMillis() - start;
System.out.printf("Took %.3f ms on average to start/stop a thread%n", (double) time/threads);
}
}
這將打印像
Took 0.055 ms on average to start/stop a thread
只有你知道這是一個很大的數字。
注意:如果你有線程本地資源,這可以使這個時間更長。這又取決於你在做什麼。
Web服務器彙集線程,這意味着稍後的請求可能使用完全相同的線程,這可以通過Thread.currentThread()。getId()獲取線程ID來觀察。不應該擔心太多,但如果您打算從servlet或過濾器創建自己的線程,請不要。這可能會導致DOS攻擊和服務器氾濫。你應該能夠通過一個servlet過濾器來添加監視功能,這將允許你在當前線程上獲取統計信息並做一些基本的性能統計。
前段時間我有一個類似的任務。我們決定堅持JMeter,但也添加了日誌到我們的代碼。我們簡單地記錄了處理我們代碼中懷疑瓶頸的特定部分花費的時間。然後我們運行JMeter讓我們的系統處於負載狀態。
這樣你就不能觀察你的所有代碼,但至少可以看到它的不同部分。
我不認爲這個解決方案很漂亮,但你可能有一個想法如何改善它。