We were actually discussing some buffer problems internally this
weekend, debating mbuf versus other solutions, etc. We needed a simple
FIFO to store data from Nordic's BLE UART service until the end user
wants to access it, and we recycled some existing FIFO code we
implemented for Nordic's SD. I was pushing to stick to standard buffers
from Mynewt (to improves odds of having pull requests accepted), but
dealing with storing 1 byte records means things like mbuf aren't very
efficient.
I'm curious what you would have done for a simple FIFO where you are
likely storing 1 or 2 bytes at a time? If there isn't a good match,
perhaps it's worth adding a very light weight FIFO or circular buffer
that can deal with very small records efficiently, but I might be
missing something that already exists?
Kevin
PS: Sorry, hijacking the discussion a bit and going off on a tangent,
but I wanted to comment since buffers will be an important part of many
libraries with Mynewt, or helper code around BLE services, and it would
be good to make sure we have options for both convenience and
performance/efficiency, just to avoid everyone reinventing the wheel.
On 19/07/16 15:38, will sanfilippo wrote:
I am +1 for mbufs. While they do take a bit of getting used to, I think
converting the host to use them is the way to go, especially if they replace a
large flat buffer pool.
I also think we should mention that mbufs use a fair amount of overhead. I dont
think that applies here as the flat buffer required for an ATT buffer is quite
large (if I recall). But if folks want to use mbufs for other things they
should be aware of this.
On Jul 18, 2016, at 5:09 PM, Christopher Collins <[email protected]> wrote:
Hello all,
This email concerns the type of data buffers that the NimBLE host
requires the application to use. There are several instances in which
buffers are passed between host and application. For example, when the
application performs a GATT write procedure, it supplies the data to
be written by passing a buffer to the host.
The core of Mynewt presents two different mechanisms for implementing
data buffers:
1. Flat bufs
2. Mbufs
A flat buf is a pointer to a region of contiguous storage and is usually
accompanied by a length argument. This is what the POSIX socket API
uses in its send() and recv() functions, for example.
Mbufs are dynamically resizable buffer chains. They are described in
much more detail here:
http://mynewt.apache.org/latest/os/core_os/mbuf/mbuf/
The NimBLE host uses flat bufs, which makes it a bit of an outlier.
Among all the core network libraries, the host appears to be the only
one whose API is not based on mbufs. In particular, I am comparing the
NimBLE host to mn_socket and newtmgr.
While it may be a bit painful to switch, I have convinced myself that it
ultimately makes more sense for the host to use mbufs instead of flat
bufs. I put together two lists: reasons to prefer flat bufs and reasons
to prefer mbufs.
Pro flat buf:
* Simple interface.
Pro mbuf:
* Consistent with the rest of Mynewt core.
* More memory efficient (no need to pre-allocate a large ATT buffer; share
memory with the rest of the system).
* More speed efficient (NimBLE host already uses mbufs internally;
no need to convert between the two buffer types).
I ordered the items in the "pro mbuf" list from most to least important,
as I see it. As much as I appreciate the simplicity of flat bufs, I
have to place a greater importance on consistency of the system as a
whole.
I have had a difficult time deciding on this issue, and I would be very
interested in hearing any and all thoughts on the subject. Absent
overwhelming disapproval, I am going to get started on implementing this
change on a separate branch. That way we will have something more
concrete to evaluate.
Thanks,
Chris