You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mynewt.apache.org by Gilles Boccon-Gibod <bo...@bok.net> on 2016/12/07 07:51:24 UTC

More throughput than should be possible?

I'm struggling with some puzzling numbers I'm getting while trying to
maximize transfer throughput over GATT.
I have a simple setup: a macbook pro sending data by writing
characteristics to a GATT server running on an nRF52DK board running mynewt.
The default MTU of 240 is accepted by the mac, and the characteristic is
setup for Write Without Response.
I am writing 200 bytes of characteristic value in a loop, as fast as
possible.
What I observe doesn't make sense: I get about 45kB/s (Kilo Bytes)
From basic calculations, the max should less than 40kB/s, unless I'm
missing something:

When blasting characteristics that way, the master will send packets with
the max PDU size (27), which should be 37 bytes (27 PDU + 10 bytes
overhead). The slave will respond with Empty PDU packets of 10 bytes each
(0 PDU + 10 bytes overhead).
If we take into account the 150 us interframe spacing, a master/slave
packet cycle should take:
296 + 150 + 80 + 150  = 676 bits (37 bytes is 296 bits). That's 676
microseconds.
With a max PDU of 27 bytes, that's 39940 bytes/s of PDU throughput.
When writing characteristics with a 200 byte value, the total payload to
transfer is 207 bytes: 200 bytes of value + 3 bytes of GATT op code and
attribute handle + 4 bytes of L2CAP length/flags. So that's a ratio of
200/207 of effective payload, which gives us 38590 bytes/s of effective
throughput in the best case.

So how can I be observing over > 45 kbytes/s in my test? Is it possible
that the interframe spacing isn't always fixed as 150 us? Or is it that
between macOS Sierra and the nrf52/mynewt stack the PDU isn't capped at 27
(which would imply LE Data Length Extension, which I thought wasn't
supported on MacOS)?

Any clues?

Re: More throughput than should be possible?

Posted by will sanfilippo <wi...@runtime.io>.
I was in the midst of writing a reply when I saw this so it looks like the question is answered. :-)

BTW: the 150 usec IFS is always fixed and cannot change.


> On Dec 7, 2016, at 10:07 AM, Gilles Boccon-Gibod <bo...@bok.net> wrote:
> 
> Thanks Chris,
> 
> this is very helpful. When I disable data length extension, I do get a much
> lower throughput. So that now makes sense.
> A strange side effect of disabling data length extension is that the mac's
> BLE stack now refuses the requested 240 MTU and sets it at 104, whereas the
> 240 value is accepted when data length extension is enabled.
> 
> On Wed, Dec 7, 2016 at 6:06 AM, Christopher Collins <cc...@apache.org>
> wrote:
> 
>> Hi Gilles,
>> 
>> I'm afraid the timing figures are a bit over my head, so I'll let the
>> resident controller expert address those.
>> 
>> Regarding data length extension on MacOS- unfortunately, I am not in a
>> position to test this at the moment, but I was under the impression that
>> recent versions of MacOS do support it.  Data length extension is
>> enabled by default in the NimBLE controller, so this is a plausible
>> explanation.
>> 
>> You can disable data length extension by setting the
>> BLE_LL_CFG_FEAT_DATA_LEN_EXT syscfg setting to 0.  This can be done as
>> follows:
>> 
>>    newt target set <target-name> syscfg=BLE_LL_CFG_FEAT_DATA_LEN_EXT=0
>> 
>> Alternatively, you can edit your target's syscfg.yml file by hand
>> (targets/<target-name>/syscfg.yml) to include the following entry:
>> 
>>    syscfg.vals:
>>        BLE_LL_CFG_FEAT_DATA_LEN_EXT: 0
>> 
>> It would be interesting to see if the throughput decreases when data
>> length extension is disabled.
>> 
>> Thanks,
>> Chris
>> 
>> On Tue, Dec 06, 2016 at 11:51:24PM -0800, Gilles Boccon-Gibod wrote:
>>> I'm struggling with some puzzling numbers I'm getting while trying to
>>> maximize transfer throughput over GATT.
>>> I have a simple setup: a macbook pro sending data by writing
>>> characteristics to a GATT server running on an nRF52DK board running
>> mynewt.
>>> The default MTU of 240 is accepted by the mac, and the characteristic is
>>> setup for Write Without Response.
>>> I am writing 200 bytes of characteristic value in a loop, as fast as
>>> possible.
>>> What I observe doesn't make sense: I get about 45kB/s (Kilo Bytes)
>>> From basic calculations, the max should less than 40kB/s, unless I'm
>>> missing something:
>>> 
>>> When blasting characteristics that way, the master will send packets with
>>> the max PDU size (27), which should be 37 bytes (27 PDU + 10 bytes
>>> overhead). The slave will respond with Empty PDU packets of 10 bytes each
>>> (0 PDU + 10 bytes overhead).
>>> If we take into account the 150 us interframe spacing, a master/slave
>>> packet cycle should take:
>>> 296 + 150 + 80 + 150  = 676 bits (37 bytes is 296 bits). That's 676
>>> microseconds.
>>> With a max PDU of 27 bytes, that's 39940 bytes/s of PDU throughput.
>>> When writing characteristics with a 200 byte value, the total payload to
>>> transfer is 207 bytes: 200 bytes of value + 3 bytes of GATT op code and
>>> attribute handle + 4 bytes of L2CAP length/flags. So that's a ratio of
>>> 200/207 of effective payload, which gives us 38590 bytes/s of effective
>>> throughput in the best case.
>>> 
>>> So how can I be observing over > 45 kbytes/s in my test? Is it possible
>>> that the interframe spacing isn't always fixed as 150 us? Or is it that
>>> between macOS Sierra and the nrf52/mynewt stack the PDU isn't capped at
>> 27
>>> (which would imply LE Data Length Extension, which I thought wasn't
>>> supported on MacOS)?
>>> 
>>> Any clues?
>> 


Re: More throughput than should be possible?

Posted by Gilles Boccon-Gibod <bo...@bok.net>.
Thanks Chris,

this is very helpful. When I disable data length extension, I do get a much
lower throughput. So that now makes sense.
A strange side effect of disabling data length extension is that the mac's
BLE stack now refuses the requested 240 MTU and sets it at 104, whereas the
240 value is accepted when data length extension is enabled.

On Wed, Dec 7, 2016 at 6:06 AM, Christopher Collins <cc...@apache.org>
wrote:

> Hi Gilles,
>
> I'm afraid the timing figures are a bit over my head, so I'll let the
> resident controller expert address those.
>
> Regarding data length extension on MacOS- unfortunately, I am not in a
> position to test this at the moment, but I was under the impression that
> recent versions of MacOS do support it.  Data length extension is
> enabled by default in the NimBLE controller, so this is a plausible
> explanation.
>
> You can disable data length extension by setting the
> BLE_LL_CFG_FEAT_DATA_LEN_EXT syscfg setting to 0.  This can be done as
> follows:
>
>     newt target set <target-name> syscfg=BLE_LL_CFG_FEAT_DATA_LEN_EXT=0
>
> Alternatively, you can edit your target's syscfg.yml file by hand
> (targets/<target-name>/syscfg.yml) to include the following entry:
>
>     syscfg.vals:
>         BLE_LL_CFG_FEAT_DATA_LEN_EXT: 0
>
> It would be interesting to see if the throughput decreases when data
> length extension is disabled.
>
> Thanks,
> Chris
>
> On Tue, Dec 06, 2016 at 11:51:24PM -0800, Gilles Boccon-Gibod wrote:
> > I'm struggling with some puzzling numbers I'm getting while trying to
> > maximize transfer throughput over GATT.
> > I have a simple setup: a macbook pro sending data by writing
> > characteristics to a GATT server running on an nRF52DK board running
> mynewt.
> > The default MTU of 240 is accepted by the mac, and the characteristic is
> > setup for Write Without Response.
> > I am writing 200 bytes of characteristic value in a loop, as fast as
> > possible.
> > What I observe doesn't make sense: I get about 45kB/s (Kilo Bytes)
> > From basic calculations, the max should less than 40kB/s, unless I'm
> > missing something:
> >
> > When blasting characteristics that way, the master will send packets with
> > the max PDU size (27), which should be 37 bytes (27 PDU + 10 bytes
> > overhead). The slave will respond with Empty PDU packets of 10 bytes each
> > (0 PDU + 10 bytes overhead).
> > If we take into account the 150 us interframe spacing, a master/slave
> > packet cycle should take:
> > 296 + 150 + 80 + 150  = 676 bits (37 bytes is 296 bits). That's 676
> > microseconds.
> > With a max PDU of 27 bytes, that's 39940 bytes/s of PDU throughput.
> > When writing characteristics with a 200 byte value, the total payload to
> > transfer is 207 bytes: 200 bytes of value + 3 bytes of GATT op code and
> > attribute handle + 4 bytes of L2CAP length/flags. So that's a ratio of
> > 200/207 of effective payload, which gives us 38590 bytes/s of effective
> > throughput in the best case.
> >
> > So how can I be observing over > 45 kbytes/s in my test? Is it possible
> > that the interframe spacing isn't always fixed as 150 us? Or is it that
> > between macOS Sierra and the nrf52/mynewt stack the PDU isn't capped at
> 27
> > (which would imply LE Data Length Extension, which I thought wasn't
> > supported on MacOS)?
> >
> > Any clues?
>

Re: More throughput than should be possible?

Posted by Christopher Collins <cc...@apache.org>.
Hi Gilles,

I'm afraid the timing figures are a bit over my head, so I'll let the
resident controller expert address those.

Regarding data length extension on MacOS- unfortunately, I am not in a
position to test this at the moment, but I was under the impression that
recent versions of MacOS do support it.  Data length extension is
enabled by default in the NimBLE controller, so this is a plausible
explanation.

You can disable data length extension by setting the
BLE_LL_CFG_FEAT_DATA_LEN_EXT syscfg setting to 0.  This can be done as
follows:

    newt target set <target-name> syscfg=BLE_LL_CFG_FEAT_DATA_LEN_EXT=0

Alternatively, you can edit your target's syscfg.yml file by hand
(targets/<target-name>/syscfg.yml) to include the following entry:

    syscfg.vals:
        BLE_LL_CFG_FEAT_DATA_LEN_EXT: 0

It would be interesting to see if the throughput decreases when data
length extension is disabled.

Thanks,
Chris

On Tue, Dec 06, 2016 at 11:51:24PM -0800, Gilles Boccon-Gibod wrote:
> I'm struggling with some puzzling numbers I'm getting while trying to
> maximize transfer throughput over GATT.
> I have a simple setup: a macbook pro sending data by writing
> characteristics to a GATT server running on an nRF52DK board running mynewt.
> The default MTU of 240 is accepted by the mac, and the characteristic is
> setup for Write Without Response.
> I am writing 200 bytes of characteristic value in a loop, as fast as
> possible.
> What I observe doesn't make sense: I get about 45kB/s (Kilo Bytes)
> From basic calculations, the max should less than 40kB/s, unless I'm
> missing something:
> 
> When blasting characteristics that way, the master will send packets with
> the max PDU size (27), which should be 37 bytes (27 PDU + 10 bytes
> overhead). The slave will respond with Empty PDU packets of 10 bytes each
> (0 PDU + 10 bytes overhead).
> If we take into account the 150 us interframe spacing, a master/slave
> packet cycle should take:
> 296 + 150 + 80 + 150  = 676 bits (37 bytes is 296 bits). That's 676
> microseconds.
> With a max PDU of 27 bytes, that's 39940 bytes/s of PDU throughput.
> When writing characteristics with a 200 byte value, the total payload to
> transfer is 207 bytes: 200 bytes of value + 3 bytes of GATT op code and
> attribute handle + 4 bytes of L2CAP length/flags. So that's a ratio of
> 200/207 of effective payload, which gives us 38590 bytes/s of effective
> throughput in the best case.
> 
> So how can I be observing over > 45 kbytes/s in my test? Is it possible
> that the interframe spacing isn't always fixed as 150 us? Or is it that
> between macOS Sierra and the nrf52/mynewt stack the PDU isn't capped at 27
> (which would imply LE Data Length Extension, which I thought wasn't
> supported on MacOS)?
> 
> Any clues?