1

I have a huge file, trying to send a portion of this file with a header and trailer. (a header + a portion of this file + trailing data)

Obvious solution is SocketChannel.write() which includes multiple system calls. So, I'm open to suggestions.

One option would be FileChannel.transferTo() but it doesn't allow to append any data before or after, so it includes 3 system calls at least.

Is there any other effective way to do it in Java? Maybe similar to FreeBSD's sendFile implementation : https://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2

Ronald
  • 13
  • 2
  • Why are you worried about the number of calls? – Robert May 17 '18 at 15:43
  • Working on an already bloated server application :) and this path will be used thousands of time per second so I'm trying to find the best way to do it. 3 calls solution with FileChannel.transferTo is quite high comparing to single FileChannel.transferTo call, so, looking for a way to decrease it. – Ronald May 17 '18 at 15:49
  • I'd get a profiler and figure out where the code spends its time. – Robert May 17 '18 at 16:20

1 Answers1

0

You can use MappedByteBuffer with scatter/gather IO.

Send performance will be closer to transferTo() as mmap also uses kernel buffers similar to sendFile() call.

Half pseudo code here, with a single write call :

MappedByteBuffer fileBuf = FileChannel.map(....);

ByteBuffer header  = ...;
ByteBuffer trailer = ...;
ByteBuffer slice   = fileBuf.slice(); // Set limit and position before slice

socketChannel.write(new ByteBuffer[]{header, slice, trailer}, 0, 3);
vkx
  • 424
  • 1
  • 7
  • 17
  • 1
    Thanks looks great!! One question though, how does sendFile and mmap use same mechanism? One maps to memory, other sends the file? How do you compare it, I didn't get it. – Ronald May 17 '18 at 16:46
  • sendFile basically maps the file into kernel buffers, then pass these buffer to socket.write. So, if you have already mmap'ed buffer which reside in kernel buffers, then socket.write might give you same performance in theory. – vkx May 17 '18 at 16:50