2013-04-12 250 views
0

我正在研究一個Android應用程序,需要與服務器(在我的電腦上運行)進行通信,這也是我寫的。 問題是InputStream.read()需要一個永恆,處理200kb大約需要30秒。也許垃圾收集涉及某種方式,在我的循環過程中,它不時被調用,但列出的延遲只有2或3毫秒,總共可能是20毫秒,所以我不認爲這是問題所在。Android InputStream.read()極其緩慢

我的代碼:

client = new Socket("192.168.1.1", 1235); 
client.setTcpNoDelay(true); 
client.setReceiveBufferSize(1048576); 
InputStream is = client.getInputStream(); 

byte[] buffer = new byte[1048576]; 
int i = 0; 
int length = -1; 

while (true) 
{ 
    int b = is.read(); 
    if (b == -1) 
    { 
     success = false; 
     break; 
    } 
    buffer[i] = (byte) b; 

    if (i == length) 
     break; 

    if (i == 3) 
    { 
     length = buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24; 
    } 

    i++; 
} 

我沒有真正經歷Java和Android中的編程總初學者,所以我不知道爲什麼它是那該死的緩慢。

+0

建議:如果您想在Android中創建服務器端客戶端應用程序,我強烈建議您檢查一下將爲您進行通信的[middleware](http://en.wikipedia.org/wiki/Middleware)例如[Apache Thrift](http://thrift.apache.org/)。 – m0skit0

回答

0

你爲什麼要單獨讀取每個字節?它看起來像你真的想讀取前3個字節,並找出你的長度,然後讀取該塊。

IE:

final byte[] lengthBuffer = new byte[3]; 

int b = is.read(lengthBuffer); 

// make sure b was 3 and do your length calculation 

final byte buffer = new byte[length]; 

b = is.read(buffer); 

// check b and then you have your bytes 

那麼你至少可以拿到的InputStream可以提供一次讀取數據塊,而不是一個字節的優化。而且你沒有像現在那樣分配這個巨型數組。

+0

好吧,這是更快,更快,甚至太快:/ 現在它完成之前所有的數據有... 順便說一句:我明白,做200k迭代沒有像優化的東西一樣快,但30秒是有趣的是,這應該仍然只需要幾毫秒,.read()必須非常低效地執行。 – Hidden

+0

好吧,我只是循環讀取直到達到長度,比讀取每個字節還要快上千倍 – Hidden

+1

@Hidden讀取的寫入效率不高 - 其訪問硬件。通過在流中進行大量小讀操作,您可以從硬緩存中進行大量小讀操作。這需要時間 - 你不再以時鐘速度運行,你受到總線時間和延遲的限制。在做網絡,存儲等任何事情時,你必須意識到最終你遇到了物理組件,並且需要寫下它們的工作方式。 –

0

您一次只讀1個字節。這是非常低效的。你想盡可能多地讀取大量的字節。這就是你的應用速度緩慢的原因。