C# 多線程猜想

来源:https://www.cnblogs.com/anxin1225/archive/2020/05/10/12861422.html
-Advertisement-
Play Games

公司分配給我一個活,讓我給Kong網關做一個獲取設置的站點。Kong網關號稱幾萬的QPS的神器,我有點慌,如果因為我的站點拖累了Kong我就是千古罪人。 配合Kong的站點必須要經過性能測試,在性能測試的時候就發現個很有意思的現象,如果我用25條線程壓我的站點,那麼結果是這樣的。 如果我用50條線程 ...


公司分配給我一個活,讓我給Kong網關做一個獲取設置的站點。Kong網關號稱幾萬的QPS的神器,我有點慌,如果因為我的站點拖累了Kong我就是千古罪人。

配合Kong的站點必須要經過性能測試,在性能測試的時候就發現個很有意思的現象,如果我用25條線程壓我的站點,那麼結果是這樣的。

 

 如果我用50條線程去壓站點,結果是這樣的

 

 現象就是,我提高了併發數量,我的QPS其實並沒有什麼變化,但是我的單次平均響應時間缺提高了一倍。其實這種現象還是比較好解釋的。首先,我們來瞭解一下,IIS的大概處理邏輯。

 

其實IIS維護了這麼幾個東西,首先一個是隊列,用來提高伺服器的同時處理請求數用的。這麼說吧,假設我現在程式很原始很簡陋,我一次只能處理一條請求,那麼,我在處理一條請求的過程中,第二條請求過來了,那麼這個時候我顯然不應該告訴他,我現在正忙,沒空搭理他,而應該是告訴他,你先等會,我馬上來處理你。讓他等會,其實就是相當於把他放到隊列裡邊,一會再來處理。

另外一個概念叫做,同時處理數。剛纔我的假設是我一次只能處理一條數據。但是我存在多個核,就算是一核在一個時間點上只能處理一條數據,那麼,現在我機器是4核的,那麼我最起碼也應該能處理4條數據,假設現在一次性來了4條數據,那麼這4條數據基本上可以認為是同時在處理的,但是如果同時來了8條數據,那麼就是4條在處理,4條在等待。

現在來解釋一下,為什麼會出現50併發比25併發,提升了等待時間,但是QPS並沒有提高。我想可以這麼解釋,其實QPS在25併發的時候已經接近於極限了,這個極限應該怎麼算呢,大概就應該是1秒 * 同時處理數 / 每個請求的真實處理時間。可以看出來這個極限其實跟客戶端的併發數沒有什麼直接聯繫。那麼50併發的時候,為什麼等待的時間反而變長了呢?那是因為,客戶端併發數大於伺服器同時處理數的時候,有一部分固定數量的請求在請求隊列里,他必須等待已經進入處理邏輯的部分處理完,然後再處理自己,所以就造成了QPS並沒有提升但是響應時間變長的現象發生。

因為是這樣的多倍疊加的模式,所以,有時候,你會發現,你的介面,如果只是幾毫秒響應的話,大家都很快。但是一旦你慢下來,響應時間是成指數級的增長。原因也很簡單,主要有以下幾個。

  • 等待的隊列邊長了(因為前邊處理的很慢,所以等的人越來越多)
  • 等待的單次邊長了(但是變長的人不止是你自己呀,還有你等待的其他人)

這幾個情況一綜合那可不是乘法運算嘛,那可不就是指數級增加嘛。

 

提問,那麼究竟多少併發,才是最理想的狀態呢?

之前考慮這個問題的時候,可能理所當然的認為,這個東西嘛,應該是跟CPU核數有關係,應該跟核數一樣多就是最優解了吧。但是現實經常啪啪打臉。經過實測,一般是要比CPU核數多少不少才是CPU不累,處理效率很高的狀態。那麼為什麼會出現這種情況呢?我覺得這個問題有點大,我們需要拆開來看。

 

1、一個核心真的是一條線程執行的最快嗎?

這個問題嘛,其實也對,也不對。說他對視因為,其實如果存在多條線程,那麼多條線程之間切換的時候,其實也挺消耗資源的。但是多線程的意義是什麼呢?我覺得這個問題也可以拆成兩個問題。在拆問題之前先給介紹兩個概念。計算密集型、IO密集型,計算密集型就是你在做運算,加減乘除也好,比對也要,加密解密也好,這種主要依賴於CPU叫計算密集型線程。如果你的線程大部分時間都消耗在了讀取網路數據,讀取本地數據,或者驅動硬體等待返回這種情況叫做IO密集型。

1.1 一個核心真的是一個計算密集型最快嗎?

是的。因為線程本身也是需要消耗資源的,頻繁的切換其實對於計算密集型線程沒有任何好處,因為計算量並沒有變少反而變多了。

1.2 一個核心真的是一個IO密集型線程最快嗎?

不對。多個IO密集型線程肯定比一個IO密集型線程要快,因為大部分時間,其實跟CPU沒有關係,CPU大部分時間都是在等而已。所以讓CPU一次性處理多個,反而更加占有優勢。

 

2、為什麼不是併發量跟同時處理數相等時是最優解。

真實的業務場景,一條線程並不是純粹的IO或者計算,更多的時候是處於兩者都有的情況。那麼對於這種線程的話。反正不是一核一個最快,因為它畢竟是存在IO的情況。他們肯定要多處理幾個才划算。

這樣伺服器等待客戶端請求的時間就太長了,如果併發數量跟處理數量相等的話,那麼對於一個併發來說,就相當於客戶端發起請求、發送網路數據、伺服器處理、發送網路數據、客戶端接收網路數據,然後進行下一輪處理。這樣的話就相當於客戶端與伺服器端處於同一個線程,單線程工作,並且中間存在了大量的等待的時間,所以伺服器的QPS並不會上來。

 

最理想的狀態應該是,以下的狀態

  • 等待隊列中始終存在數據(不會讓處理線程等待客戶端請求)
  • 客戶端的請求進入等待隊列後立馬被處理(不會因為別的請求而造成響應時間過長,而引發下一步的等待隊列過長)

根據上邊總結的多線程的相關結論,一般一個核心肯定要處理多個線程,並且等待隊列中存在並且存在不了多少數據。

那麼最佳併發的結論應該是,核心數 * N(單核心同時處理線程數) + M(等待隊列中存在的少數請求)。

 

題外話:為什麼Golang號稱利用協成能夠更好的利用CPU 達到更高的運算效率呢?

我猜應該是將IO型線程中的多線程切換部分性能節省下來,用作於更多的CPU計算來提高了整體性能。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 記錄一下如何用python爬取app數據,本文以爬取抖音視頻app為例。 編程工具:pycharm app抓包工具:mitmproxy app自動化工具:appium 運行環境:windows10 思路: 假設已經配置好我們所需要的工具 1、使用mitmproxy對手機app抓包獲取我們想要的 ...
  • 一、MyBatis-Plus 1、簡介 MyBatis-Plus 是一個 Mybatis 增強版工具,在 MyBatis 上擴充了其他功能沒有改變其基本功能,為了簡化開發提交效率而存在。 官網文檔地址: https://mp.baomidou.com/guide/ MyBatis-Plus 特性: ...
  • eclipse4.15 增加了該功能 下麵是官方更新說明 谷歌翻譯 啟用方法 ...
  • 1、安裝第三方庫並引入 import CameraRoll from '@react-native-community/cameraroll'; import RNFS from 'react-native-fs'; Github參考鏈接:CameraRoll RNFS 2、添加許可權 <uses-p ...
  • swoole實現視頻彈幕效果 轉自:https://www.cnblogs.com/xinliangcoder/p/10800910.html ...
  • java異常介紹 異常時相對於return的一種退出機制,可以由系統觸發,也可由程式通過throw語句觸發,異常可以通過try/catch語句進行捕獲並處理,如果沒有捕獲,則會導致程式退出並輸出異常棧信息,異常有不同的類型,所有異常類都有一個共同的父類Throwable,下麵我們先從Throwabl ...
  • 1. 論Conv2d()里的padding和Conv2d()前padding的區別及重要性。 小生建議,儘量少用Conv2d()里的填充方式,換成自定義填充方式(強烈建議)。 小生為何這樣建議呢,是因為小生以前就常使用Conv2d()里的padding方式,覺得這樣使用簡單、不麻煩(O(∩_∩)O哈 ...
  • 7.整數反轉Java版,每日一題系列(此題來自力扣網) 給出一個31位的有符號整數,你需要將這個整數中每位上數字進行反轉。 示例1: 輸入: 123輸出: 321 示例2: 輸入: -123輸出: -321 示例3: 輸入: 120輸出: 21 方法:彈出和推入數字&溢出前進行檢查 思路 我們可以一 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...