I have a process that receives a lot of requests and i'm running some load tests using Apache Bench to find out why it's so slow (240 requests/second).
I've isolated all points and i found what the part that is slow:
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()
}
This is the code after i did some optimizations but still slow - before the optimization it was 98 requests/second and now i have 240 requests/second.
Anybody could help me how to improve this method? I'm creating a ByteArrayOutoutStream and adding X-Send again because this must the first line on file.
Thank in advance.
Writing bytes: 322 requests/second.
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()
}
It's not clear to me what mailMessage.writeTo(baos, Array[String]("X-Sender"))
actually does, but it feels like your initial code is being very wasteful in converting everything to a string and back, and even your second code is doing a lot of stuff in memory that can go straight to disk:
// TODO: Try wrapping this in a BufferedOutputStream
try (FileOutputStream output = new FileOutputStream(outputPath)) {
mailMessage.writeTo(output, Array[String]("X-Sender"));
}
Basically, the more intervening steps you remove, the less work will be required. If mailMessage.writeTo
writes to the stream it's given in lots of small chunks, using a BufferedOutputStream
may help - you should test that for yourself.
See more on this question at Stackoverflow