jakartaee / jakartaee/mail-api
Performance problem with reading the content of a body part
- Dominant language
- Java
- Stars
- 285
- Forks
- 109
- Avg merge
- 15h 19m
- Merged PRs (30d)
- 1
Description
**Is your feature request related to a problem? Please describe.**
We're replacing the `cid:` references with base64 encoded images. These images must be read from the corresponding (mime) body part. However the reading operation is way too slow. We have a test email with a 6.3 MB inlined image and this is a common scenario for us.
**Describe the solution you'd like**
The problem comes from the `BASE64DecoderStream` implementation. Despite that it's not too effective to get a decoded content to encode it again, the input stream itself is reading the content too slow.
This input stream is got using the `bodyPart.getInputStream()` function so we cannot do too much there.
It would be nice to either get the whole base64 content as-is or read the content in bigger blocks (preferably the whole content in one go) and decode after that.
**Describe alternatives you've considered**
First we thought that writing to the output stream is slow so we implemented a custom buffered byte array output. The input stream's read operation is called with a large block size (1MB at least) but it didn't make any noticable difference.
Then we tried saving the content to a file [as we can read in the FAQ](https://eclipse-ee4j.github.io/mail/FAQ#readattach). It was a bit slower than reading the content to a byte array.
**Additional context**
We benchmarked the application and the result in each implementation was about the same: 10.5-11.5 seconds to extract a 6.3MB base64 encoded png file. We tried:
* to read the image with the custom big-block-output-buffer implementation
* to read the image with the simple output buffer
```
final var outStream = new ByteArrayOutputStream();
contentPart.getDataHandler().writeTo(outStream);
// same with contentPart.getInputStream().transferTo(outStream);
```
* to save the file with the built-in saveFile function
Re-encoding the byte array to base64 takes about 50 ms.
Contributor guide
Research direction
Start with BASE64DecoderStream and trace the read path reached through bodyPart.getInputStream(), comparing it with the large-block and DataHandler writeTo approaches described. Reproduce the 6.3 MB benchmark, then verify that content extraction is materially faster without changing decoded output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- performance
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100