Low number of requests/second on process that writes files on disk

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()
}
Jon Skeet
people
quotationmark

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.

people

See more on this question at Stackoverflow