2015-06-15 13 views
0

我有一個進程接收很多請求,並且我正在運行一些使用Apache Bench進行的加載測試以查明它爲什麼如此緩慢(240個請求/秒) 。在磁盤上寫入文件的進程中請求數/秒數較少

我已經分離出的所有點,我發現那是什麼慢的部分:

def writeEmailToFile(mailMessage:MimeMessage, outputPath:String) ={ 
    val baos = new ByteArrayOutputStream(); 
    mailMessage.writeTo(baos, Array[String]("X-Sender")) 
    baos.close() 
    /* 
    //after i'll need to include it as first line 
    val emailContent = new StringBuilder() 
    emailContent.append("X-Sender: ") 
    emailContent.append(mailMessage.getHeader("X-Sender")(0)) 
    emailContent.append(System.getProperty("line.separator")) 
    emailContent.append(new String(baos.toByteArray, "UTF-8")) 
    */ 
    val fw = new FileWriter(outputPath) 
    fw.write(new String(baos.toByteArray, "UTF-8")) 
    fw.flush() 
    fw.close() 
} 

這是代碼後,我做了一些優化,但仍慢 - 優化前是98個請求/秒,現在我有240個請求/秒。

任何人都可以幫助我如何改進這種方法?我創建了一個ByteArrayOutoutStream並再次添加X-Send,因爲這必須是文件的第一行。

提前致謝。

寫入字節數:322個請求/秒。

def writeEmailToFile(mailMessage:MimeMessage, outputPath:String) ={ 
    val baos = new ByteArrayOutputStream() 
    val outputStream = new FileOutputStream(outputPath) 
    mailMessage.writeTo(baos, Array[String]("X-Sender")) 
    baos.writeTo(outputStream) 
    outputStream.flush() 
    outputStream.close() 
    baos.flush() 
    baos.close() 
} 
+1

除了其他任何東西,你爲什麼要將字節數組轉換爲字符串?爲什麼不直接將二進制數據寫入磁盤? (這將採取*你的一些CPU *很可能相當數量。) –

+0

我這樣做是因爲我需要編寫被評論的代碼。 X發件人必須在第一行。你知道如何在X-Sender內容(如fw.write(「blabla」); fw.write(binary)?)之後編寫二進制數據? – placplacboom

+1

好吧,無論如何,我會'OutputStreamWriter'寫出文本,刷新寫入,然後將二進制數據直接寫入基礎流。 –

回答

2

這不是很清楚,我什麼mailMessage.writeTo(baos, Array[String]("X-Sender"))實際上做了,但感覺像您最初的代碼是在一切轉換成字符串和背部非常浪費,甚至是你的第二個代碼做了很多的東西在內存可以直接進入磁盤:

// TODO: Try wrapping this in a BufferedOutputStream 
try (FileOutputStream output = new FileOutputStream(outputPath)) { 
    mailMessage.writeTo(output, Array[String]("X-Sender")); 
} 

基本上,您移除的干預步驟越多,所需的工作就越少。如果mailMessage.writeTo寫入流中,它會以很多小塊給出,但使用BufferedOutputStream可能會有幫助 - 您應該自己測試一下。

+0

我試過兩種方法,仍然停留在310-322個請求/秒。也許這是限制,我應該考慮實施負載均衡。你的解決方案非常優雅,但它不適合我,因爲在寫入文件之前我需要操作數據,而當我爲它準備時,我還會有另一個缺口。如果我使用StringBuilder來創建數據,而不是MimeMessage,那麼我的吞吐量會更低:262請求/秒。另一點是直接連接到SMTP,而不是寫入文件。 – placplacboom

+0

@placplacboom:這就是爲什麼我問你是否在記憶中需要它 - 你說你沒有。如果您在將文件寫入文件之前需要對其進行操作,那麼您清楚*做*。如果需求發生變化,很難爲您提供幫助。儘管如此,我會嘗試在水平方向上縮放而不是垂直縮放。 –

+0

我的錯,對不起。我會與基礎設施談判以擴大規模。我們優化了所有代碼和數據庫調用,但是當我們開始在磁盤上寫入文件時,這是一場災難 - 非常緩慢。而我們正在使用虛擬機,我曾要求增加內存和處理器,但沒有幸運。非常感謝你的幫助。 – placplacboom