Sent too early!

mmap version:

https://github.com/jvz/nio-logger/blob/master/src/main/java/org/musigma/logging/appender/MemoryMappedFileAppender.java

I'm going to rerun the benchmarks. I think I'm getting closer to finding
some things we've missed in the NIO API (plus now I actually have a much
better understanding on how the hell channels and buffers work).

On 26 February 2017 at 23:10, Matt Sicker <boa...@gmail.com> wrote:

> Whoops, totally forgot some links. So here is a basic FileChannelAppender
> (though in log4j-core, this would likely be a Manager instead along with a
> zillion other features I'm not bothering to reimplement in a playground
> project):
>
> https://github.com/jvz/nio-logger/blob/master/src/main/
> java/org/musigma/logging/appender/FileChannelAppender.java
>
> I've also done similarly with the mmap file version:
>
>
> On 26 February 2017 at 23:08, Matt Sicker <boa...@gmail.com> wrote:
>
>> I'm testing out a simplified system that pretty much tests out how fast
>> different appenders and encoding styles can work. Log messages here do not
>> have any information besides a message and a timestamp. It's to investigate
>> what possible NIO optimizations are possible in Log4j 2.
>>
>> Anyways, I've fixed the performance of the FileChannelAppender, too. By
>> using the equivalent of ByteBufferDestination here (I called it Buffered<T
>> extends Buffer> for now), this not only provided buffering for free (well,
>> it's kind of the point), but by using direct allocation of a ByteBuffer,
>> the transfer from the encoded message in said buffer into the FileChannel
>> is a lot faster (in theory, the OS can bypass some things to make the
>> transfer faster or something; I'm not super clear on the details).
>>
>> One thing I've already discovered is that unless there's some reason not
>> to, we should be using ByteBuffer.allocateDirect(size) instead of
>> ByteBuffer.wrap(new byte[size]) when the underlying IO class uses
>> ByteBuffer instead of byte[]. It might improve performance of the
>> OutputStream-based appenders, too, but I haven't really tested this in the
>> full project.
>>
>> On 26 February 2017 at 22:53, Ralph Goers <ralph.go...@dslextreme.com>
>> wrote:
>>
>>> I’m not sure what these numbers mean as I don’t know what you’ve changed
>>> and how they compare to what was there previously.
>>>
>>> Ralph
>>>
>>> On Feb 26, 2017, at 9:44 PM, Matt Sicker <boa...@gmail.com> wrote:
>>>
>>> Anyways, I managed to implement MemoryMappedFileAppender in the
>>> playground by basically copying it from log4j-core. Everything is still in
>>> a state of flux here, but without adding manual buffering to the
>>> FileChannel and RandomAccessFile appenders, here are my current results
>>> (the async channel one is still failing):
>>>
>>> Benchmark                                        Mode  Cnt        Score
>>>       Error  Units
>>> FileChannelAppenderBenchmark.logToFile          thrpt   10   306320.023
>>> ±  4911.376  ops/s
>>> FileOutputStreamAppenderBenchmark.logToFile     thrpt   10  1311134.313
>>> ± 32814.148  ops/s
>>> MemoryMappedFileAppenderBenchmark.logToFile     thrpt   10  1569499.970
>>> ± 47550.210  ops/s
>>> NioFileOutputStreamAppenderBenchmark.logToFile  thrpt   10  1414480.114
>>> ± 39527.202  ops/s
>>> RandomAccessFileAppenderBenchmark.logToFile     thrpt   10   422874.583
>>> ±  5457.952  ops/s
>>>
>>> On 26 February 2017 at 21:39, Matt Sicker <boa...@gmail.com> wrote:
>>>
>>>> I noticed that in MemoryMappedFileManager, if the MappedByteBuffer
>>>> hasn't been fully written to when remap() is called, then the new
>>>> MappedByteBuffer will include the unwritten area as well as an additional
>>>> region of the file. Do you think this could cause issues with performance
>>>> like we saw with the highly variable throughput in the appender? I'm
>>>> guessing the idea here is to continue writing wherever we left off but
>>>> while also providing a larger ByteBuffer for producers to use if the
>>>> normally sized one is too small. But in that case, the producer can simply
>>>> keep draining the buffer as it goes.
>>>>
>>>> On 26 February 2017 at 19:27, Remko Popma <remko.po...@gmail.com>
>>>> wrote:
>>>>
>>>>> Afonso, are you a robot?
>>>>>
>>>>> On Mon, Feb 27, 2017 at 8:44 AM, Afonso Murakami <
>>>>> murakam...@icloud.com> wrote:
>>>>>
>>>>>> That is great thank you very much for your help
>>>>>>
>>>>>> On Feb 26, 2017, at 3:36 PM, Matt Sicker <boa...@gmail.com> wrote:
>>>>>>
>>>>>> Afonso, are you on the right mailing list?
>>>>>>
>>>>>> Anyways, I've made more updates to my playground. Without
>>>>>> implementing manual buffering on top of RandomAccessFile or FileChannel 
>>>>>> (or
>>>>>> the async file channel, but that one has a bug in it right now causing 
>>>>>> OOM
>>>>>> errors occasionally which is probably due to a misunderstanding on how 
>>>>>> many
>>>>>> ByteBuffers I can queue up asynchronously before I'm supposed to stop and
>>>>>> wait), the Java 101 style of using new BufferedOutputStream(new
>>>>>> FileOutputStream(file)) is currently the fastest appender I have. I'm 
>>>>>> also
>>>>>> trying to implement a MappedByteBuffer version, but now I'm rediscovering
>>>>>> the reason why we have a ByteBufferDestination interface (plus all I'm
>>>>>> getting as a result are 2 GB files filled with nulls, so I'm doing
>>>>>> something wrong here anyways).
>>>>>>
>>>>>> I was also able to fix some strange performance issues in the tests
>>>>>> that were being caused by my Layout implementation, so I've swapped in a
>>>>>> trivial one that assumes input is in ASCII and casts chars to bytes to
>>>>>> encode them. In Java 9, we may be able to do something with the compacted
>>>>>> strings thing they added for ISO-8859-1 strings.
>>>>>>
>>>>>> There are also some additional benchmarks added that I found
>>>>>> interesting while comparing some approaches. For one, copying from a
>>>>>> directly-allocated ByteBuffer into a byte[] (via ByteBuffer::get(byte[]))
>>>>>> is almost twice as fast as copying from a heap-allocated ByteBuffer into 
>>>>>> a
>>>>>> byte[]. Another interesting thing I found was that doing new
>>>>>> Date().toString() is faster than Instant.now().toString().
>>>>>>
>>>>>> On 26 February 2017 at 16:10, Afonso Murakami <murakam...@icloud.com>
>>>>>> wrote:
>>>>>>
>>>>>>> Thank you for your help and time .
>>>>>>>
>>>>>>> On Feb 26, 2017, at 2:05 PM, Matt Sicker <boa...@gmail.com> wrote:
>>>>>>>
>>>>>>> So far I've discovered that my implementation of Layout that uses
>>>>>>> CharsetEncoder.encode(CharBuffer, ByteBuffer, boolean) is slower
>>>>>>> than the version that just uses CharsetEncoder.encode(CharBuffer).
>>>>>>> That could be causing issues here.
>>>>>>>
>>>>>>> I did try out FileChannel, and based on my current implementations,
>>>>>>> it's around the same speed as using Files.newOutputStream(). My
>>>>>>> AsynchronousFileChannel usage must be incorrect as it's working much 
>>>>>>> slower
>>>>>>> than the synchronous form.
>>>>>>>
>>>>>>> On 26 February 2017 at 13:03, Afonso Murakami <murakam...@icloud.com
>>>>>>> > wrote:
>>>>>>>
>>>>>>>> I don’t know if that make any difference but I click on the link
>>>>>>>> https://githhub.com/vz/nio-looger to see what is about and when I
>>>>>>>> finished I sign of on my account may that screw up something or may be 
>>>>>>>> not,
>>>>>>>> I’m not sure if Idid that or not, sorry.
>>>>>>>>
>>>>>>>> On Feb 26, 2017, at 10:49 AM, Matt Sicker <boa...@gmail.com> wrote:
>>>>>>>>
>>>>>>>> I could be doing something wrong entirely here, but so far, the
>>>>>>>> fastest way I've found to write to a file (not including mmap yet) is 
>>>>>>>> via:
>>>>>>>>
>>>>>>>> new BufferedOutputStream(Files.newOutputStream(Paths.get("test.l
>>>>>>>> og")))
>>>>>>>>
>>>>>>>> And this is with added synchronization on the append() method, too.
>>>>>>>> Also, one of my updates to the async channel version is causing OOM 
>>>>>>>> errors
>>>>>>>> in JMH now, so I broke something.
>>>>>>>>
>>>>>>>> On 26 February 2017 at 12:22, Matt Sicker <boa...@gmail.com> wrote:
>>>>>>>>
>>>>>>>>> I added some basic JMH tests to my repo along with a couple
>>>>>>>>> alternative appender implementations. I got rid of the unnecessary 
>>>>>>>>> file
>>>>>>>>> region locking in the async file channel one, but it's still coming 
>>>>>>>>> out
>>>>>>>>> quite a bit slower than the RandomAccessFile and 
>>>>>>>>> Files.newOutputStream()
>>>>>>>>> based appenders, though that could be due to the use of Phaser (which 
>>>>>>>>> I
>>>>>>>>> only added to cleanly close the appender synchronously).
>>>>>>>>>
>>>>>>>>> On 26 February 2017 at 10:05, Matt Sicker <boa...@gmail.com>
>>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>> Perhaps something got optimized by the JVM? I'll add some JMH
>>>>>>>>>> tests to this repo to try out various approaches.
>>>>>>>>>>
>>>>>>>>>> On Sat, Feb 25, 2017 at 21:12, Apache <ralph.go...@dslextreme.com>
>>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>> I tried using a FileChannel for the FileAppender a week or so
>>>>>>>>>>> ago to see if passing the ByteBuffer to the FileChannel would 
>>>>>>>>>>> improve
>>>>>>>>>>> performance since it doesn’t have to be synchronized. I didn’t see 
>>>>>>>>>>> any
>>>>>>>>>>> improvement though and I ended up reverting it. But I might have 
>>>>>>>>>>> done
>>>>>>>>>>> something wrong.
>>>>>>>>>>>
>>>>>>>>>>> Ralph
>>>>>>>>>>>
>>>>>>>>>>> On Feb 25, 2017, at 4:19 PM, Matt Sicker <boa...@gmail.com>
>>>>>>>>>>> wrote:
>>>>>>>>>>>
>>>>>>>>>>> We already use a bit of NIO (ByteBuffer for layouts and
>>>>>>>>>>> appenders/managers, MappedByteBuffer for mmap'd files, FileLock for 
>>>>>>>>>>> locking
>>>>>>>>>>> files, etc.), and I've been playing around with the NIO API lately. 
>>>>>>>>>>> I have
>>>>>>>>>>> some sample code here <https://github.com/jvz/nio-logger> to
>>>>>>>>>>> show some trivial use case of AsynchronousFileChannel. In Java 7, 
>>>>>>>>>>> there is
>>>>>>>>>>> also AsynchronousSocketChannel which could theoretically be used 
>>>>>>>>>>> instead of
>>>>>>>>>>> adding Netty for a faster socket appender. In that regard, I'm 
>>>>>>>>>>> curious as
>>>>>>>>>>> to how useful it would be to have similar appenders as the 
>>>>>>>>>>> OutputStream
>>>>>>>>>>> ones, but instead using WritableByteChannel, GatheringByteChannel 
>>>>>>>>>>> (possible
>>>>>>>>>>> parallelization of file writing?), and the async channels (there's 
>>>>>>>>>>> an
>>>>>>>>>>> AsynchronousByteChannel class, but I think they screwed this one up 
>>>>>>>>>>> as only
>>>>>>>>>>> one of the three async channel classes implements it).
>>>>>>>>>>>
>>>>>>>>>>> Another related issue I've seen is that in a message-oriented
>>>>>>>>>>> appender (e.g., the Kafka one), being able to stream directly to a
>>>>>>>>>>> ByteBuffer is not the right way to go about encoding log messages 
>>>>>>>>>>> into the
>>>>>>>>>>> appender. Instead, I was thinking that a pool of reusable 
>>>>>>>>>>> ByteBuffers could
>>>>>>>>>>> be used here where a ByteBuffer is borrowed on write and returned on
>>>>>>>>>>> completion (via a CompletionHandler callback). The Kafka client 
>>>>>>>>>>> uses a
>>>>>>>>>>> similar strategy for producing messages by dynamically allocating a 
>>>>>>>>>>> pool of
>>>>>>>>>>> ByteBuffers based on available memory.
>>>>>>>>>>>
>>>>>>>>>>> Also, I don't have much experience with this, but if we had a
>>>>>>>>>>> pool of reusable ByteBuffers, could we use direct allocation to get
>>>>>>>>>>> off-heap buffers? That seems like an interesting use case.
>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>>> Matt Sicker <boa...@gmail.com>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>> Matt Sicker <boa...@gmail.com>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Matt Sicker <boa...@gmail.com>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> --
>>>>>>>> Matt Sicker <boa...@gmail.com>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> Matt Sicker <boa...@gmail.com>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Matt Sicker <boa...@gmail.com>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> Matt Sicker <boa...@gmail.com>
>>>>
>>>
>>>
>>>
>>> --
>>> Matt Sicker <boa...@gmail.com>
>>>
>>>
>>>
>>
>>
>> --
>> Matt Sicker <boa...@gmail.com>
>>
>
>
>
> --
> Matt Sicker <boa...@gmail.com>
>



-- 
Matt Sicker <boa...@gmail.com>

Reply via email to