Commit Graph

82 Commits

Author SHA1 Message Date
Chris Vest
7b48263184 Re-enable the cleaner tests and make them run faster 2021-05-05 16:09:11 +02:00
Chris Vest
2ab8dd65eb Remove unused imports 2021-05-05 16:09:11 +02:00
Chris Vest
599c01b762 Make the buffer read-only state irreversible
This greatly simplifies the semantics around the const buffers.
When they can no longer be made writable, there is no longer any need for "deconstification".

I decided to call the method "makeReadOnly" to distinguish it from "asReadOnly" that is seen in ByteBuf and ByteBuffer. The latter two return read-only _views_ of the buffer, while makeReadOnly changes the state of the buffer in-place.
2021-05-05 12:30:52 +02:00
Chris Vest
51cc1e7cf4 More efficient const buffer implementations
The const buffers of the various implementations are now able to share the underlying memory.
At least until they are forced not to.
Const buffers will behave ust like normal buffers, except they start out as read-only.
When they are made writable, or sliced, then they will allocate their own independent copy of the memory.
That way, const buffers can have their contents changed, and behave just like normal buffers.
The const-ness is a pure optimisation that should not have any externally observable behaviour.
2021-05-03 15:00:49 +02:00
Chris Vest
d247ddeae3 Try speeding up the build some more
The number of tests we run is increasing
2021-05-02 17:07:58 +02:00
Chris Vest
3281f72369 First draft of const buffers and how to have buffers as constants
Currently only has a strawman implementation.
2021-04-30 15:35:40 +02:00
Chris Vest
66c2bf4e2c Rename bifurcate to split 2021-04-29 15:34:04 +02:00
Chris Vest
6506e29569 Make tests on composite buffers pass again 2021-04-28 12:33:40 +02:00
Chris Vest
f2033263dd Replace CompositeBuffer.extendComposite with extendWith 2021-04-27 16:11:30 +02:00
Chris Vest
2f12455fa9 Make CompositeBuffer part of the public API
And move the composite buffer related methods to it.
2021-04-27 16:11:30 +02:00
Chris Vest
49deb77fd3 Allow running AlternativeMessageDecoderTest from Maven 2021-04-27 14:09:27 +02:00
Chris Vest
25b234acd2 Make the BufferBulkAccessTest.writeBytesMustTransferDataAndUpdateOffsets test run faster
Only run a sample of 10% of the possible combinations, and then run them in parallel.
2021-04-27 13:33:28 +02:00
Chris Vest
60954394a5 Use Send.isSendOf to simplify code 2021-04-27 10:03:24 +02:00
Chris Vest
926a1807b4 Clean up code and remove the BufferAdaptor
Instead use Mockito to implement the throwing behaviour on the buffers in those tests.
Sadly Mockito cannot spy or mock our Buffer implementation classes, and does not allow mocking an interface while spying on an implementation, so we have to do a more complicated dance with our mocking.
2021-04-27 10:00:27 +02:00
Chris Vest
8c2987a824 Add a Buffer.writeBytes bulk transfer method
This simplifies some of the ByteToMessageDecoder example code.
2021-04-27 10:00:27 +02:00
Chris Vest
d72982a5ef Fix checkstyle issue 2021-04-27 10:00:27 +02:00
Chris Vest
0748d206d2 Add an alternative message decoder implementation
This one is a rewrite, making use of the new APIs where possible.
The test uses bifurcate to cut buffers into segments.
2021-04-27 10:00:27 +02:00
Chris Vest
c081c73885 Port over the ByteToMessageDecoder as an example 2021-04-27 10:00:27 +02:00
Chris Vest
7775460984 Make bifurcate and ensureWritable more flexible
This supports more use cases.
The ensureWritable method can now amortise its allocation cost by allocating more than what is strictly necessary to satisfy the immediate call.
The bifurcate method can now split at a given offset.
2021-04-27 10:00:27 +02:00
Chris Vest
2decac081a Rename Deref.isInstanceOf to referentIsInstanceOf
Motivation:
Derefs are not necessarily their referents.
This is the case for Send, for instance.

Modification:
The Deref.isInstanceOf method is renamed to referentIsInstanceOf.
And a Send.isSendOf method has been added, that simplifies the check for sends, since it could be the case that one also needs to check if the object in question is also a Send instance.

Result:
Cleaner code that is easier to read, when working with Sends.

This fixes https://github.com/netty/netty-incubator-buffer-api/issues/46
2021-04-26 18:33:52 +02:00
Chris Vest
fdc59cc43c Break up the monolithic BufferTest into multiple test classes
Then run those tests in independent surefire forks.
This should allow Maven to hold on to less test metadata, and cope better with the large number of tests.
2021-04-14 11:44:58 +02:00
Chris Vest
55348fb660 Give more memory to surefire when running the full test suite
There are so many tests now that their metadata takes up a considerable amount of memory.
2021-04-13 15:18:14 +02:00
Chris Vest
a3dfaf535d Fix test sample filtering and disable really slow tests 2021-04-08 11:08:09 +02:00
Chris Vest
7fda986d2c Make CleanerTests faster by reducing iteration count 2021-04-07 17:43:51 +02:00
Chris Vest
987a398700 Fix native memory leak bug
Motivation:
The untethered memory allocated by ensureWritable in a direct MemorySegment based non-pooled Buffer would be allocated without having a Cleaner attached to its ResourceScope.
This could cause that memory to leak if the Buffer instance was cast aside.

Modification:
ManagedBufferAllocator now makes sure to attach a cleaner to the buffer and its memory segment, when allocating untethered memory.

Result:
The BufferTest$CleanerTests now pass.
2021-04-07 17:17:35 +02:00
Chris Vest
ab45a7b053 Fix (some) failing tests
Also introduce test sampling, so when the BufferTest is running from an IDE, only 3% of the tests will actually run.

The Maven build runs all tests.
2021-04-07 16:19:35 +02:00
Chris Vest
513cef1c1e Update code to support bleeding edge MemorySegment APIs after the latest refactoring 2021-04-07 14:28:05 +02:00
Chris Vest
3e6eceb58a Make it possible to run all tests in Intellij as well
The previous set-up was only working out for Maven.
2021-03-24 11:21:00 +01:00
Chris Vest
95709828bf Add a ByteBuffer based implementation of Buffer
Motivation:
We need a new implementation of our new API that supports Java 11, since that is what Netty 5 will most likely baseline on.
We also need an implementation that does not rely on Unsafe.
This leaves us with ByteBuffer as the underlying currency of memory.

Modification:
- Add a NioBuffer implementation and associated supporting classes.
- The entry-point for this is a new MemoryManagers API, which is used to pick the implementation and provide the on-/off-heap MemoryManager implementations.
- Add a mechanism to configure/override which MemoryManagers implementation to use.
- The MemoryManagers implementations are service-loadable, so new ones can be discovered at runtime.
- The existing MemorySegment based implementation also get a MemoryManagers implementation.
- Expand the BufferTest to include all combinations of all implementations. We now run 360.000 tests in BufferTest.
- Some common infrastructure, like ArcDrop, is moved to its own package.
- Add a module-info.java to control the service loading, and the visibility in the various packages.
- Some pom.xml file updates to support our now module based project.

Result:
We have an implementation that should work on Java 11, but we currently don't build or test on 11.
More work needs to happen before that is a reality.
2021-03-18 15:18:22 +01:00
Chris Vest
de305bd6b9 Align slice sendability of composite buffers with that of non-composite buffers
This means we no longer need to have tests that are parameterised over non-sliced buffers.
2021-03-16 17:22:41 +01:00
Chris Vest
0ccb34ca08 Fix failing ByteBufAdaptorTests and increase adaptor compatibility 2021-03-16 12:11:29 +01:00
Chris Vest
253b6cb919 Allow slices to obtain ownership when parent is closed
Motivation:
It is kind of a weird internal and hidden state, that slices were special.
For instance, slices could not be sent, and they could never obtain ownership.
This means buffers from slices behaved differently from allocated buffers.
In doing so, they violated both the principle that magic should stay hidden, and the principle of consistent behaviour.

Modification:
- The special reference-counting drop implementation that was added to support bifurcation, has been renamed to ArcDrop (for atomic reference counting).
- The ArcDrop is then used throughout the MemSegBuffer implementation to account for every instance where multiple buffers reference the same memory, e.g. slices and the like.
- Borrows of a buffer is then the sum of borrows from the buffer itself, and its ArcDrop.
- Ownership is thus tied to both the buffer itself being owned, and the ArcDrop being in an owned state.
- SizeClassedMemoryPool is changed to pool recoverable memory instead of sends, because the sends could come from slices.
- We also take care to keep around a "base" memory segment, so that we don't return memory segment slices to the memory pool (doing so would leak the memory from the parent segment that is not part of the slice).
- CleanerPooledDrop now keeps a weak reference to itself, rather than the buffer, which is more correct anyway, but now also required because we cannot rely on the buffer reference the cleaner was created with.
- The CleanerPooledDrop now takes care to drop the buffer that is actually passed to it, rather than what it was referencing from some earlier point.
- MemoryManager can now disclose the size of recoverable memory, so that SizeClassedMemoryPool can pick the correct size pool to return memory to. It cannot rely on the passed down buffer instance for this, because that buffer might have been a slice.

Result:
It is now possible for slices to obtain ownership when their parent buffer is closed.
2021-03-15 16:42:56 +01:00
Chris Vest
f775e2cf97 Get the last ByteBufAdaptor tests passing 2021-03-09 16:48:33 +01:00
Chris Vest
2dee6f8516 Fix bounds checking bugs when setting bytes
These should not take the read offset into account.
2021-03-09 16:16:38 +01:00
Chris Vest
da70f29ff4 Fix numerous bugs in the ByteBufAdaptor 2021-03-09 12:04:57 +01:00
Chris Vest
45074e4749 Try to speed up BufferTest with more parameter memoization and parallel execution 2021-03-09 12:03:33 +01:00
Chris Vest
56bfa22d4a Align Buffer.get* bounds checks with their documented behaviour
The get* methods bounds checking accesses between 0 and the write offset, and the tests were confirming this behaviour.

This was wrong because it is not symmetric with the set* methods, which bounds check between 0 and the capacity, and does not modify the write offset.

The tests and methods have been updated so the get* methods now bounds check between 0 and the capacity.
2021-03-09 12:02:46 +01:00
Chris Vest
2f9aabc915 Create AbstractByteBufTest for ByteBufAdaptor
There are a number of test failures that needs to be looked at, still.
2021-03-06 11:22:25 +01:00
Chris Vest
8d31917bc6 The HttpUpload example *almost* works
There are some weird off-by-one artefacts where ASCII period and newline character bytes switch places.
This needs more investigation.
2021-03-06 11:21:17 +01:00
Chris Vest
602389712c Add working HttpSnoop example 2021-03-06 11:18:14 +01:00
Chris Vest
78f04eeb49 Update docs and examples 2021-03-01 11:21:25 +01:00
Chris Vest
1b65bf9a23 Make the incubating buffers exposable as ByteBuf
Motivation:
This makes it possible to use the new buffer API in Netty as is.

Modification:
Make the MemSegBuffer implementation class implement AsByteBuf and ReferenceCounted.
The produced ByteBuf instance delegates all calls to the underlying Buffer instance as faithfully as possible.
One area where the two deviates, is that it's not possible to create non-retained duplicates and slices with the new buffer API.

Result:
It is now possible to use the new buffer API on both client and server side.
The Echo* examples demonstrate this, and the EchoIT proves it with a test.
The API is used more directly on the client side, since the server-side allocator in Netty does not know how to allocate buffers with the incubating API.
2021-03-01 10:49:09 +01:00
Chris Vest
6175f8f4c5 Make ReadableComponent expose ByteCursors
Motivation:
Another way to process the readable data in a buffer.
This might be faster for composite buffers, since their byte cursors are a bit slower than the MemSegBuffer due to the indirections and more complicated logic.

Modification:
ReadableComponent now have openCursor method.

Note that we *don't* add an openReverseCursor method on ReadableComponent.
The reason is that forEachReadable iterates the components in the forward direction, and it's really confusing to then iterate the bytes in a backwards direction.
Working with both directions at the same time is very error prone.

Result:
It is now possible to process readable components with byte cursors.
2021-02-27 11:04:44 +01:00
Chris Vest
7185a59f7a Move composite buffer methods to Buffer
Motivation:
There is no reason for `compose()` to be an instance method on `BufferAllocator` since the allocator implementation should not influence how this method is implemented.

Modification:
Make `compose()` a static method and move it to the `Buffer` interface.
Also move its companion methods `extendComposite()` and `isComposite()` to the `Buffer` interface.

Result:
The composite buffer methods are now in a more sensible place.

Also: decided _against_ making `extendComposite()` and `isComposite()` instance methods, because the subtle behaviours of `extendComposite()` means it would behave quite differently for non-composite buffers.
Also: `isComposite()` is not an instance method because it relates to the hard-coded and concrete `CompositeBuffer` implementation.
2021-02-15 17:46:23 +01:00
Chris Vest
eef97dd1fd Rename Buf to Buffer and Allocator to BufferAllocator 2021-02-12 18:22:07 +01:00
Chris Vest
492977d9be Introduce Deref abstraction
Motivation:
Sometimes, we wish to operate on both buffers and anything that can produce a buffer.
For instance, when making a composite buffer, we could compose either buffers or sends.

Modification:
Introduce a Deref interface, which is extended by both Rc and Send.
A Deref can be used to acquire an Rc instance, and in doing so will also acquire a reference to the Rc.
That is, dereferencing increases the reference count.
For Rc itself, this just delegates to Rc.acquire, while for Send it delegates to Send.receive, and can only be called once.
The Allocator.compose method has been changed to take Derefs.
This allows us to compose either Bufs or Sends of bufs.
Or a mix.
Extra care and caution has been added to the code, to make sure the reference counts are managed correctly when composing buffers, now that it's a more complicated operation.
A handful of convenience methods for working with Sends have also been added to the Send interface.

Result:
We can now build a composite buffer out of sends of buffers.
2021-02-11 14:26:57 +01:00
Chris Vest
2df000ad9a Update examples
Motivation:
The forEachReadable/Writable permit a cleaner FileCopyExample implementation.

Modification:
Simplify FileCopyExample.
Also add examples of various good and bad ways to transfer buffer ownership between threads.
Update the forEachReadable/Writable APIs to let exceptions pass through.

Result:
Cleaner code and more useful forEachReadable/Writable APIs.
2021-01-25 13:23:26 +01:00
Chris Vest
14d55c3e0b Avoid nesting composite buffers
Motivation:
There is no reason that composite buffers should nest when composed.
Instead, when composite buffers are used to compose or extend other composite buffers, we should unwrap them and copy the references to their constituent buffers.

Modification:
Composite buffers now always unwrap and flatten themselves when they participate in composition or extension of other composite buffers.

Result:
Composite buffers are now always guaranteed* to contain a single level of non-composed leaf buffers.

*assuming no other unknown buffer-wrapping buffer type is in the mix.
2021-01-18 16:06:53 +01:00
Chris Vest
1c10770e82 Implement segregated readable/writable component interfaces and processing 2021-01-15 21:32:24 +01:00
Chris Vest
46ed14577c Add Buf.forEachWritable
Pass iteration indexes through.
2021-01-15 16:11:21 +01:00