前言
巴中網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、響應(yīng)式網(wǎng)站設(shè)計(jì)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)自2013年創(chuàng)立以來(lái)到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。
不知道大家對(duì)throttle這個(gè)單詞是否看著眼熟,還是說(shuō)對(duì)這個(gè)計(jì)算機(jī)基礎(chǔ)概念有很清晰的了解了。今天就來(lái)聊聊和throttle相關(guān)的一些技術(shù)場(chǎng)景。
定義
我經(jīng)常有一種感覺(jué),對(duì)于英語(yǔ)這門(mén)語(yǔ)言的語(yǔ)感,會(huì)影響我們對(duì)于一些關(guān)鍵技術(shù)概念的理解。有時(shí)候在學(xué)習(xí)新技術(shù)知識(shí)的時(shí)候,我會(huì)先花一些時(shí)間去了解術(shù)語(yǔ)英文單詞的各種語(yǔ)義,在形成強(qiáng)烈清晰的語(yǔ)感之后,再去深入具體的技術(shù)語(yǔ)境。throttle也算是個(gè)生僻的單詞,至少在口語(yǔ)中畢竟少用到,先來(lái)看看詞義:
a device controlling the flow of fuel or power to an engine.
中文翻譯是節(jié)流器,一種控制流量的設(shè)備。對(duì)應(yīng)到我們計(jì)算機(jī)世界,可以理解成,一種控制數(shù)據(jù)或者事件流量大小的機(jī)制。這么說(shuō)可能還是有些抽象,再來(lái)看看一些具體的技術(shù)場(chǎng)景加深理解。
場(chǎng)景一:GCD Background Queue
話說(shuō)GCD幾乎是iOS面試的必問(wèn)題,也是個(gè)送分題:)。
我一般會(huì)機(jī)械式的先問(wèn):GCD有哪幾種Queue?回答:串行Queue和并行Queue。
我繼續(xù)問(wèn):Global Queue有哪幾種優(yōu)先級(jí)?回答:有幾種吧,大概記得Default,Low,High吧。
我雙眉一挑,進(jìn)一步試探:不知道少俠有沒(méi)有研究過(guò)DISPATCH_QUEUE_PRIORITY_BACKGROUND作何用?問(wèn)完立即豎起耳朵,殷殷期盼縈繞于心的關(guān)鍵字。如果能聽(tīng)到「I/O Throttle 呀!」,我會(huì)瞬間覺(jué)得面試氣氛被點(diǎn)亮了。
當(dāng)然啦,答不出I/O Throttle并不能說(shuō)明技術(shù)不扎實(shí),但能答出來(lái),至少表明對(duì)待技術(shù)是有好奇心的,加分!
官方文檔如是說(shuō):
Items dispatched to the queue run at background priority; the queue is scheduled for execution after all high priority queues have been scheduled and the system runs items on a thread whose priority is set for background status. Such a thread has the lowest priority and any disk I/O is throttled to minimize the impact on the system.
那Disk I/O Throttle做什么用呢?按照上面這段描述,Disk I/O會(huì)impact system performance。
理解Disk I/O的影響需要補(bǔ)充一些大學(xué)課本上的知識(shí)。一次磁盤(pán)讀寫(xiě)操作涉及到的硬件資源主要有兩個(gè),CPU和磁盤(pán)。任務(wù)本身由CPU觸發(fā)和調(diào)度,讀操作發(fā)生時(shí),CPU告知Disk去獲取某個(gè)地址的數(shù)據(jù),此時(shí)由于Disk的讀操作存在尋址延遲,CPU是處于I/O wait狀態(tài),一直維持到Disk返回?cái)?shù)據(jù)為止。處于I/O wait狀態(tài)的CPU,此時(shí)并不能把這部分等待的時(shí)間用來(lái)處理其他任務(wù),也就是說(shuō)這一段等待的CPU時(shí)間被“浪費(fèi)”了。而CPU是公共的系統(tǒng)資源,這部分資源的損耗自然會(huì)對(duì)系統(tǒng)的整體表現(xiàn)產(chǎn)生負(fù)面影響。即使Global Queue使用的是子線程,也會(huì)造成CPU資源的消耗。
如果把任務(wù)的Priority調(diào)整為DISPATCH_QUEUE_PRIORITY_BACKGROUND,那么這些任務(wù)中的I/O操作就被被控制,雖然具體的控制策略并沒(méi)有官方文檔描述(一種可能的策略是并發(fā)的Disk I/O變?yōu)榇械模?,但我們能確認(rèn)的是,部分I/O操作的啟動(dòng)時(shí)間很有可能被適當(dāng)延遲,把更多的CPU資源騰出來(lái)處理其他任務(wù)(比如說(shuō)一些系統(tǒng)資源的調(diào)度任務(wù)),這樣可以讓我們的系統(tǒng)更加穩(wěn)定高效。簡(jiǎn)而言之,對(duì)于重度磁盤(pán)I/O依賴的后臺(tái)任務(wù),如果對(duì)實(shí)時(shí)性要求不高,放到DISPATCH_QUEUE_PRIORITY_BACKGROUND Queue中是個(gè)好習(xí)慣,對(duì)系統(tǒng)更友好。
實(shí)際上I/O Throttle還分為好幾種,有Disk I/O Throttle,Memory I/O Throttle,和Network I/O Throttle。語(yǔ)義類似只不過(guò)場(chǎng)景不同,繼續(xù)往下看。
場(chǎng)景二:ASIHttpRequest Network Throttle
早幾年讀ASIHttpRequest源碼的時(shí)候,讀到過(guò)一段有意思的代碼:
- (void)handleNetworkEvent:(CFStreamEventType)type { //... [self performThrottling]; //... }
在AFNetworking中也有類似的代碼:
/** Throttles request bandwidth by limiting the packet size and adding a delay for each chunk read from the upload stream. When uploading over a 3G or EDGE connection, requests may fail with "request body stream exhausted". Setting a maximum packet size and delay according to the recommended values (`kAFUploadStream3GSuggestedPacketSize` and `kAFUploadStream3GSuggestedDelay`) lowers the risk of the input stream exceeding its allocated bandwidth. Unfortunately, there is no definite way to distinguish between a 3G, EDGE, or LTE connection over `NSURLConnection`. As such, it is not recommended that you throttle bandwidth based solely on network reachability. Instead, you should consider checking for the "request body stream exhausted" in a failure block, and then retrying the request with throttled bandwidth. @param numberOfBytes Maximum packet size, in number of bytes. The default packet size for an input stream is 16kb. @param delay Duration of delay each time a packet is read. By default, no delay is set. */ - (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes delay:(NSTimeInterval)delay;
原諒我貼了一大段注釋,這段英文描述對(duì)于加深我們對(duì)于一些網(wǎng)絡(luò)行為的理解很有幫助。
這些知名的第三方網(wǎng)絡(luò)框架都有對(duì)Newtork Throttle的支持,你可能會(huì)好奇,我們?yōu)槭裁匆獙?duì)自己發(fā)出的網(wǎng)絡(luò)請(qǐng)求做流量控制,難道不應(yīng)該盡可能最大限度的利用帶寬嗎?
此處需要科普一點(diǎn)TCP協(xié)議相關(guān)的知識(shí)。我們通過(guò)HTTP請(qǐng)求發(fā)送數(shù)據(jù)的時(shí)候,實(shí)際上數(shù)據(jù)是以Packet的形式存在于一個(gè)Send Buffer中的,應(yīng)用層平時(shí)感知不到這個(gè)Buffer的存在。TCP提供可靠的傳輸,在弱網(wǎng)環(huán)境下,一個(gè)Packet一次傳輸失敗的概率會(huì)升高,即使一次失敗,TCP并不會(huì)馬上認(rèn)為請(qǐng)求失敗了,而是會(huì)繼續(xù)重試一段時(shí)間,同時(shí)TCP還保證Packet的有序傳輸,意味著前面的Packet如果不被ack,后面的Packet就會(huì)繼續(xù)等待,如果我們一次往Send Buffer中寫(xiě)入大量的數(shù)據(jù),那么在弱網(wǎng)環(huán)境下,排在后面的Packet失敗的概率會(huì)變高,也就意味著我們HTTP請(qǐng)求失敗的幾率會(huì)變大,類似這樣:
大部分時(shí)候在應(yīng)用層寫(xiě)代碼的時(shí)候,估計(jì)不少同學(xué)都意識(shí)不到Newtork Throttle這種機(jī)制的存在,在弱網(wǎng)環(huán)境下(丟包率高,帶寬低,延遲高)一些HTTP請(qǐng)求(比如上傳圖片或者日志文件)失敗率會(huì)激增,有些朋友會(huì)覺(jué)得這個(gè)我們也沒(méi)辦法,畢竟網(wǎng)絡(luò)辣么差。其實(shí),作為有追求的工程師,我們可以多做一點(diǎn)點(diǎn),而且弱網(wǎng)下請(qǐng)求的成功率其實(shí)是個(gè)很值得深入研究的方向。針對(duì)弱網(wǎng)場(chǎng)景,我們可以啟用Newtork Throttle機(jī)制,減小我們一次往Send Buffer中寫(xiě)入的數(shù)據(jù)量,或者延遲某些請(qǐng)求的發(fā)送時(shí)間,這樣所有的請(qǐng)求在弱網(wǎng)環(huán)境下,都能「耐心一點(diǎn),多等一會(huì)」,請(qǐng)求成功率自然也就適當(dāng)提高啦。
那么,再看AFNetworking中的這個(gè)函數(shù),是不是更能理解了呢?
- (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes delay:(NSTimeInterval)delay;
Network Throttle體現(xiàn)了一句至理名言「慢即是快」。
場(chǎng)景三:Event Frequency Control
不知道大家在寫(xiě)UI的時(shí)候,有沒(méi)有遇到過(guò)用戶快速連續(xù)點(diǎn)擊UIButton,產(chǎn)生多次Touch事件回調(diào)的場(chǎng)景。以前機(jī)器還沒(méi)那么快的時(shí)候,我在用一些App的時(shí)候,時(shí)不時(shí)會(huì)遇到偶爾卡頓,多次點(diǎn)擊一個(gè)Button,重復(fù)Push同一個(gè)Controller。有些工程師會(huì)在Button的點(diǎn)擊事件里記錄一個(gè)timestamp,然后判斷每次點(diǎn)擊的時(shí)間間隔,間隔過(guò)短就忽略,這也不失為一種解決辦法。
再后來(lái)學(xué)習(xí)RxSwift的時(shí)候,看到:
button.rx_tap .throttle(0.5, MainScheduler.instance) .subscribeNext { _ in print("Hello World") } .addDisposableTo(disposeBag)
終于有了優(yōu)雅的書(shū)寫(xiě)方式。發(fā)現(xiàn)沒(méi)有,throttle又出現(xiàn)了,這里throttle控制的是什么呢?不是disk讀寫(xiě),也不是network buffer,而是事件,把事件本身抽象成了一種Data,控制這種數(shù)據(jù)的流量或者產(chǎn)生頻率,就解決了上面我們所說(shuō)重復(fù)點(diǎn)擊按鈕的問(wèn)題,so easy。
總結(jié)
當(dāng)然還會(huì)有更多的場(chǎng)景,throttle其實(shí)是個(gè)基礎(chǔ)的計(jì)算機(jī)知識(shí)。理解throttle相關(guān)的技術(shù)概念,需要在不同場(chǎng)景下去抽象出一個(gè)flow被節(jié)流的畫(huà)面。現(xiàn)在,如果讓你來(lái)解釋一些具體的技術(shù)場(chǎng)景下,throttle是怎么回事,是不是可以信手拈來(lái)了:)
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)創(chuàng)新互聯(lián)的支持。