bxfjb commented on issue #8017:
URL: https://github.com/apache/rocketmq/issues/8017#issuecomment-2056779446

   > > > `ByteStreams.toByteArray()` creates large array in memory and is 
unnecessary. It seems `FileChannel.transferFrom()` with NIO channel would be 
more efficient for writing streams to a file.
   > > 
   > > 
   > > Thx for reply, I tried `FileChannel.transferFrom()` but find out some 
unittest failed:
   > > ```
   > > @Test
   > > public void consumeQueueTest() throws ClassNotFoundException, 
NoSuchMethodException {
   > >     ...
   > >     ByteBuffer cqItem1 = fileSegment.read(initPosition, unitSize);
   > >     Assert.assertEquals(baseOffset, cqItem1.getLong());  // failed
   > >     ...
   > > }
   > > ```
   > > 
   > > 
   > >     
   > >       
   > >     
   > > 
   > >       
   > >     
   > > 
   > >     
   > >   
   > > > java.lang.AssertionError:
   > > > Expected :1000
   > > > Actual   :0
   > > 
   > > 
   > > It turns out the cq data was not flush correctly by debugging, I wonder 
if the way I use `FileChannel.transferFrom()` is wrong: Before:
   > > ```
   > >                 byte[] byteArray = ByteStreams.toByteArray(inputStream);
   > >                 writeFileChannel.position(position);
   > >                 ByteBuffer buffer = ByteBuffer.wrap(byteArray);
   > >                 while (buffer.hasRemaining()) {
   > >                     writeFileChannel.write(buffer);
   > >                 }
   > >                 writeFileChannel.force(true);
   > > ```
   > > 
   > > 
   > >     
   > >       
   > >     
   > > 
   > >       
   > >     
   > > 
   > >     
   > >   
   > > After:
   > > ```
   > >                 ReadableByteChannel readableByteChannel = 
Channels.newChannel(inputStream);
   > >                 writeFileChannel.transferFrom(readableByteChannel, 
position, length);
   > >                 writeFileChannel.force(true);
   > > ```
   > 
   > It seems the modification is not equivalent. 
`writeFileChannel.position(position)` has side effect, making 
`writeFileChannel` written from `position`. But 
`writeFileChannel.transferFrom()` exits when `position` is larger than the size 
of `writeFileChannel`.
   > 
   > You might extend the file of `writeFileChannel` to `position` and also 
check if the transferred bytes is equal to `length`.
   
   Agree with you. But then I was wondering if the failed unittest necessary, 
it seems acting like: 
   - set a empty file's commitPosition to 100
   - append some mocked ConsumeQueue Buffer to it
   - `commitPosition` is larger than the size of `writeFileChannel`, commit 
failed
   
   Is it acceptable to remove step 1 in `consumeQueueTest`? @lizhimins 'cause 
the scenario seems nonexistent in production.
   
   Furthermore, `FileChannel.read()` has the same problem with 
`FileChannel.write()`, but to return a `ByteBuffer`, calling it looks like 
inevitable. I didn't find out how to use `FileChannel.transferTo()` to replace 
it completely. I'd like to use `MappedByteBuffer` as a alternative.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@rocketmq.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to