[英]Why is Android socket reading so slow periodically?
套接字創建如下:
Socket socket = new Socket();
socket.setReuseAddress(true);
socket.setSoTimeout(iTimeout);
socket.connect(new InetSocketAddress(InetAddress.getByName(uri.getHost()), iPort), 6000);
socket.setReceiveBufferSize(iReceiveBufferSize); //iReceiveBufferSize = 1024*256
final InputStream is = socket.getInputStream();
為了提出這個問題,我們創建並測試了一個調試方法:
public void SocketDebug(InputStream isSocketInput)
{
try {
byte[] abBuffer = new byte[1024*256];
for(int i = 0; i < 1000; i++)
{
long lStart = System.currentTimeMillis();
int iRead = isSocketInput.read(abBuffer, 1024 * 10, 1024 * 128);
int iElapse = (int)(System.currentTimeMillis() - lStart);
if(iElapse > 100)
{
utility.logd("Debug", "i:" + i + " iElapse:" + iElapse + " iRead:" + iRead);
}
}
}
catch(Exception ex)
{
}
}
以下是logcat記錄的內容的一部分:
01-Jun 37:26.8 i:9 iElapse:234 iRead:1448
01-Jun 37:29.5 i:114 iElapse:299 iRead:1448
01-Jun 37:29.8 i:126 iElapse:298 iRead:1448
01-Jun 37:30.1 i:132 iElapse:300 iRead:1448
01-Jun 37:30.4 i:139 iElapse:283 iRead:1448
01-Jun 37:30.7 i:146 iElapse:287 iRead:1448
01-Jun 37:31.0 i:160 iElapse:269 iRead:1448
01-Jun 37:31.3 i:169 iElapse:251 iRead:44888
01-Jun 37:31.5 i:170 iElapse:192 iRead:1448
01-Jun 37:31.7 i:185 iElapse:170 iRead:1448
01-Jun 37:32.0 i:198 iElapse:171 iRead:1448
01-Jun 37:32.2 i:217 iElapse:158 iRead:1448
01-Jun 37:32.5 i:240 iElapse:162 iRead:1448
01-Jun 37:32.7 i:259 iElapse:135 iRead:1448
01-Jun 37:33.0 i:281 iElapse:103 iRead:1448
01-Jun 37:34.2 i:324 iElapse:826 iRead:1448
01-Jun 37:34.4 i:330 iElapse:233 iRead:1448
01-Jun 37:34.7 i:336 iElapse:264 iRead:1448
01-Jun 37:35.0 i:341 iElapse:299 iRead:1448
01-Jun 37:35.3 i:346 iElapse:300 iRead:1448
01-Jun 37:35.6 i:352 iElapse:297 iRead:1448
01-Jun 37:36.0 i:354 iElapse:317 iRead:21720
01-Jun 37:36.3 i:355 iElapse:304 iRead:13032
數據源是視頻流服務器。 大多數情況下,isSocketInput.read()只需1到3毫秒(上面的日志中沒有顯示)。 但是,周期性地需要100到1000毫秒。 查看紅色字節數,顯然1448是TCP有效負載。 所有紅色字節的數量都是1448的倍數。人們可能認為服務器發送TCP數據包可能需要很長時間。 很難理解的是isSocketInput.read()有時會讀取如此多的數據包(例如31個數據包= 44888個字節)並且需要很長時間才能返回。 它是否應該在有任何數據時盡快返回?
當運行SocketDebug()時,應用程序的所有其他線程基本上都進入休眠狀態(即在包含Thread.sleep()的循環中)。
任何人都可以提供有關長插座讀取時間的可能原因的提示嗎?
更新(2015-06-03):
上述測試是使用帶有單核CPU(Asus MeMO)的Android平板電腦完成的。 當使用具有四核CPU(AGPTek TP714AQ)的低端通用Android平板電腦進行測試時,isSocketInput.read()使用的時間顯着改善。 在前200次迭代之后,長時間過去的次數減少到零。 即使在最初的200次左右的迭代中,也只有少數很長的時間(> 100 ms)。
在這個時候,我認為單核CPU設備的長期過去主要是由答案中提到的“進程或線程被重新調度”引起的 ,這在單核CPU設備上更頻繁地發生。
它無法以比數據到達更快的速度讀取,並且不會比發送數據更快地發生。 不要責怪接收代碼,責怪發件人或網絡。
當您獲得更多字節數時,可能是在您阻塞更長時間之后,並且在您的進程或線程再次重新計划之前到達了更多數據。 您無法從代碼中控制它。
筆記:
setReceiveBufferSize()
,而不是之后調用。 這樣窗口縮放就可以生效了。 setReuseAddress()
是沒有意義的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.