* seastar temporary_buffer/packet and ceph::buffer
@ 2018-01-15 15:49 kefu chai
2018-01-15 16:53 ` kefu chai
2018-01-15 17:19 ` Casey Bodley
0 siblings, 2 replies; 14+ messages in thread
From: kefu chai @ 2018-01-15 15:49 UTC (permalink / raw)
To: The Esoteric Order of the Squid Cybernetic, Casey Bodley
hey Casey,
i've been thinking about how to better integrate
seastar::temporary_buffer and seastar::packet into our denc and
messenger subsystems based on your wip-seastar-msg branch.
as you pointed out to me that
> the conversions between ceph::buffer::ptr and seastar::temporary_buffer in https://github.com/cbodley/ceph/tree/wip-seastar-msg/ work, but they cost an allocation in both directions (seastar::make_object_deleter() has to allocate for type erasure).
and just like ceph::buffer::ptr, seastar::temporary_buffer also
manages the life cycle of the underlying memory chunk using refcount.
it's a waste to do the refcounting for the same mem chunk twice in the
same application.
if we want to avoid the overhead of duplicated refcounting and
allocation in the conversion to and from ceph::buffer::ptr, i think,
we need to allocate the temporary_buffer along with buffer::ptr. in
other words, to include seastar::temporary_buffer as a member variable
in ceph::buffer:ptr.
i am preparing a change to prototype this approach. the downside of it is:
- we need to include a placeholder structure in buffer.h for
seastar::tempoary_buffer<char>. and cast it to
seastar::tempoary_buffer<char> in buffer.cc . otherwise we need to
include seastar headers in librados.
cheers,
--
Regards
Kefu Chai
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-15 15:49 seastar temporary_buffer/packet and ceph::buffer kefu chai
@ 2018-01-15 16:53 ` kefu chai
2018-01-15 17:04 ` Piotr Dałek
2018-01-15 17:19 ` Casey Bodley
1 sibling, 1 reply; 14+ messages in thread
From: kefu chai @ 2018-01-15 16:53 UTC (permalink / raw)
To: The Esoteric Order of the Squid Cybernetic, Casey Bodley
On Mon, Jan 15, 2018 at 11:49 PM, kefu chai <tchaikov@gmail.com> wrote:
> hey Casey,
>
>
> i've been thinking about how to better integrate
> seastar::temporary_buffer and seastar::packet into our denc and
> messenger subsystems based on your wip-seastar-msg branch.
>
> as you pointed out to me that
>
>> the conversions between ceph::buffer::ptr and seastar::temporary_buffer in https://github.com/cbodley/ceph/tree/wip-seastar-msg/ work, but they cost an allocation in both directions (seastar::make_object_deleter() has to allocate for type erasure).
>
> and just like ceph::buffer::ptr, seastar::temporary_buffer also
> manages the life cycle of the underlying memory chunk using refcount.
> it's a waste to do the refcounting for the same mem chunk twice in the
> same application.
>
> if we want to avoid the overhead of duplicated refcounting and
> allocation in the conversion to and from ceph::buffer::ptr, i think,
> we need to allocate the temporary_buffer along with buffer::ptr. in
> other words, to include seastar::temporary_buffer as a member variable
> in ceph::buffer:ptr.
>
> i am preparing a change to prototype this approach. the downside of it is:
>
> - we need to include a placeholder structure in buffer.h for
> seastar::tempoary_buffer<char>. and cast it to
> seastar::tempoary_buffer<char> in buffer.cc . otherwise we need to
> include seastar headers in librados.
- we cannot store the crc map along with the raw class anymore. this
might be a show stopper.
- we can not use zero copy interfaces anymore. but i think it's fine.
as we need to use future/promise based interfaces for IO.
>
> cheers,
>
>
> --
> Regards
> Kefu Chai
--
Regards
Kefu Chai
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-15 16:53 ` kefu chai
@ 2018-01-15 17:04 ` Piotr Dałek
2018-01-15 17:09 ` kefu chai
0 siblings, 1 reply; 14+ messages in thread
From: Piotr Dałek @ 2018-01-15 17:04 UTC (permalink / raw)
To: kefu chai; +Cc: The Esoteric Order of the Squid Cybernetic, Casey Bodley
On Tue, Jan 16, 2018 at 12:53:22AM +0800, kefu chai wrote:
> On Mon, Jan 15, 2018 at 11:49 PM, kefu chai <tchaikov@gmail.com> wrote:
> > [..]
> > i am preparing a change to prototype this approach. the downside of it is:
> >
> > - we need to include a placeholder structure in buffer.h for
> > seastar::tempoary_buffer<char>. and cast it to
> > seastar::tempoary_buffer<char> in buffer.cc . otherwise we need to
> > include seastar headers in librados.
>
> - we cannot store the crc map along with the raw class anymore. this
> might be a show stopper.
https://github.com/ceph/ceph/pull/18906
There, already fixed it.
--
Piotr Dałek
branch@predictor.org.pl
http://blog.predictor.org.pl
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-15 17:04 ` Piotr Dałek
@ 2018-01-15 17:09 ` kefu chai
2018-01-15 17:13 ` Piotr Dałek
0 siblings, 1 reply; 14+ messages in thread
From: kefu chai @ 2018-01-15 17:09 UTC (permalink / raw)
To: Piotr Dałek; +Cc: The Esoteric Order of the Squid Cybernetic, Casey Bodley
On Tue, Jan 16, 2018 at 1:04 AM, Piotr Dałek <branch@predictor.org.pl> wrote:
> On Tue, Jan 16, 2018 at 12:53:22AM +0800, kefu chai wrote:
>> On Mon, Jan 15, 2018 at 11:49 PM, kefu chai <tchaikov@gmail.com> wrote:
>> > [..]
>> > i am preparing a change to prototype this approach. the downside of it is:
>> >
>> > - we need to include a placeholder structure in buffer.h for
>> > seastar::tempoary_buffer<char>. and cast it to
>> > seastar::tempoary_buffer<char> in buffer.cc . otherwise we need to
>> > include seastar headers in librados.
>>
>> - we cannot store the crc map along with the raw class anymore. this
>> might be a show stopper.
>
> https://github.com/ceph/ceph/pull/18906
> There, already fixed it.
Piotr, thanks for point me to this PR. but i am evaluating the pros
and cons of the change, which tries to replace buffer::raw with
seastar::temporary_buffer, and use the latter in buffer::ptr as a
member variable.
>
> --
> Piotr Dałek
> branch@predictor.org.pl
> http://blog.predictor.org.pl
--
Regards
Kefu Chai
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-15 17:09 ` kefu chai
@ 2018-01-15 17:13 ` Piotr Dałek
0 siblings, 0 replies; 14+ messages in thread
From: Piotr Dałek @ 2018-01-15 17:13 UTC (permalink / raw)
To: kefu chai; +Cc: The Esoteric Order of the Squid Cybernetic, Casey Bodley
On Tue, Jan 16, 2018 at 01:09:57AM +0800, kefu chai wrote:
> On Tue, Jan 16, 2018 at 1:04 AM, Piotr Dałek <branch@predictor.org.pl> wrote:
> > On Tue, Jan 16, 2018 at 12:53:22AM +0800, kefu chai wrote:
> >> On Mon, Jan 15, 2018 at 11:49 PM, kefu chai <tchaikov@gmail.com> wrote:
> >> > [..]
> >> > i am preparing a change to prototype this approach. the downside of it is:
> >> >
> >> > - we need to include a placeholder structure in buffer.h for
> >> > seastar::tempoary_buffer<char>. and cast it to
> >> > seastar::tempoary_buffer<char> in buffer.cc . otherwise we need to
> >> > include seastar headers in librados.
> >>
> >> - we cannot store the crc map along with the raw class anymore. this
> >> might be a show stopper.
> >
> > https://github.com/ceph/ceph/pull/18906
> > There, already fixed it.
>
> Piotr, thanks for point me to this PR. but i am evaluating the pros
> and cons of the change, which tries to replace buffer::raw with
> seastar::temporary_buffer, and use the latter in buffer::ptr as a
> member variable.
And I'm pointing out that there's no need to worry about crc map anymore,
because it's gone.
--
Piotr Dałek
branch@predictor.org.pl
http://blog.predictor.org.pl
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-15 15:49 seastar temporary_buffer/packet and ceph::buffer kefu chai
2018-01-15 16:53 ` kefu chai
@ 2018-01-15 17:19 ` Casey Bodley
2018-01-15 19:30 ` Matt Benjamin
1 sibling, 1 reply; 14+ messages in thread
From: Casey Bodley @ 2018-01-15 17:19 UTC (permalink / raw)
To: kefu chai, The Esoteric Order of the Squid Cybernetic
Hi Kefu, thanks for your feedback on this!
To add some context for the list, I had commented on Kefu's denc pr at
https://github.com/ceph/ceph/pull/19662#issuecomment-355602713 about
integrating ceph encode/decode with buffer types from other frameworks,
using the seastar types as an example (seastar::temporary_buffer is a
buffer segment with ownership semantics, so shares a lot in common with
ceph::bufferptr).
My approach in the seastar messenger added buffer conversions either by
wrapping the seastar::temporary_buffer inside of a raw buffer type, or
by wrapping our ceph::bufferptr inside a seastar::temporary_buffer's
deleter object. So the conversions in both directions cost an allocation.
On 01/15/2018 10:49 AM, kefu chai wrote:
> hey Casey,
>
>
> i've been thinking about how to better integrate
> seastar::temporary_buffer and seastar::packet into our denc and
> messenger subsystems based on your wip-seastar-msg branch.
>
> as you pointed out to me that
>
>> the conversions between ceph::buffer::ptr and seastar::temporary_buffer in https://github.com/cbodley/ceph/tree/wip-seastar-msg/ work, but they cost an allocation in both directions (seastar::make_object_deleter() has to allocate for type erasure).
> and just like ceph::buffer::ptr, seastar::temporary_buffer also
> manages the life cycle of the underlying memory chunk using refcount.
> it's a waste to do the refcounting for the same mem chunk twice in the
> same application.
>
> if we want to avoid the overhead of duplicated refcounting and
> allocation in the conversion to and from ceph::buffer::ptr, i think,
> we need to allocate the temporary_buffer along with buffer::ptr. in
> other words, to include seastar::temporary_buffer as a member variable
> in ceph::buffer:ptr.
>
> i am preparing a change to prototype this approach. the downside of it is:
>
> - we need to include a placeholder structure in buffer.h for
> seastar::tempoary_buffer<char>. and cast it to
> seastar::tempoary_buffer<char> in buffer.cc . otherwise we need to
> include seastar headers in librados.
>
> cheers,
>
>
Interesting, I hadn't thought about adding it as a member of bufferptr.
That would be add some size overhead for non-seastar buffers though,
unless we were able to reuse that for all raw buffer types. I agree that
we want to be careful about dependencies, though, so I was really hoping
to avoid this kind of coupling. I'd really prefer not to have any of our
common libraries depend on seastar, and only link it directly to the
targets that need it.
My initial idea was that, if we were able to refactor denc in terms of
some generic buffer concept, we'd be able to use ceph's encode/decode on
external buffer types without the need to convert to/from bufferlist in
the first place. That would allow us to support seastar's buffer types,
and also extend support to other types like boost::asio's buffer
concepts as well.
So my comment on your pr was asking more about specific features that
denc requires from bufferlist, so that we could start to generalize them
in a way that doesn't have bufferlist baked in.
Thanks,
Casey
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-15 17:19 ` Casey Bodley
@ 2018-01-15 19:30 ` Matt Benjamin
2018-01-15 20:48 ` Casey Bodley
0 siblings, 1 reply; 14+ messages in thread
From: Matt Benjamin @ 2018-01-15 19:30 UTC (permalink / raw)
To: Casey Bodley; +Cc: kefu chai, The Esoteric Order of the Squid Cybernetic
It's the buffer::raw class that abstracts foreign buffer
representations now, is it now? A mechanism to allow seastar to
single-allocate a composite buffer::raw and temporary_buffer<char>
seems possible to imagine.
Matt
On Mon, Jan 15, 2018 at 12:19 PM, Casey Bodley <cbodley@redhat.com> wrote:
> Hi Kefu, thanks for your feedback on this!
>
> To add some context for the list, I had commented on Kefu's denc pr at
> https://github.com/ceph/ceph/pull/19662#issuecomment-355602713 about
> integrating ceph encode/decode with buffer types from other frameworks,
> using the seastar types as an example (seastar::temporary_buffer is a buffer
> segment with ownership semantics, so shares a lot in common with
> ceph::bufferptr).
>
> My approach in the seastar messenger added buffer conversions either by
> wrapping the seastar::temporary_buffer inside of a raw buffer type, or by
> wrapping our ceph::bufferptr inside a seastar::temporary_buffer's deleter
> object. So the conversions in both directions cost an allocation.
>
> On 01/15/2018 10:49 AM, kefu chai wrote:
>>
>> hey Casey,
>>
>>
>> i've been thinking about how to better integrate
>> seastar::temporary_buffer and seastar::packet into our denc and
>> messenger subsystems based on your wip-seastar-msg branch.
>>
>> as you pointed out to me that
>>
>>> the conversions between ceph::buffer::ptr and seastar::temporary_buffer
>>> in https://github.com/cbodley/ceph/tree/wip-seastar-msg/ work, but they cost
>>> an allocation in both directions (seastar::make_object_deleter() has to
>>> allocate for type erasure).
>>
>> and just like ceph::buffer::ptr, seastar::temporary_buffer also
>> manages the life cycle of the underlying memory chunk using refcount.
>> it's a waste to do the refcounting for the same mem chunk twice in the
>> same application.
>>
>> if we want to avoid the overhead of duplicated refcounting and
>> allocation in the conversion to and from ceph::buffer::ptr, i think,
>> we need to allocate the temporary_buffer along with buffer::ptr. in
>> other words, to include seastar::temporary_buffer as a member variable
>> in ceph::buffer:ptr.
>>
>> i am preparing a change to prototype this approach. the downside of it is:
>>
>> - we need to include a placeholder structure in buffer.h for
>> seastar::tempoary_buffer<char>. and cast it to
>> seastar::tempoary_buffer<char> in buffer.cc . otherwise we need to
>> include seastar headers in librados.
>>
>> cheers,
>>
>>
>
> Interesting, I hadn't thought about adding it as a member of bufferptr. That
> would be add some size overhead for non-seastar buffers though, unless we
> were able to reuse that for all raw buffer types. I agree that we want to be
> careful about dependencies, though, so I was really hoping to avoid this
> kind of coupling. I'd really prefer not to have any of our common libraries
> depend on seastar, and only link it directly to the targets that need it.
>
> My initial idea was that, if we were able to refactor denc in terms of some
> generic buffer concept, we'd be able to use ceph's encode/decode on external
> buffer types without the need to convert to/from bufferlist in the first
> place. That would allow us to support seastar's buffer types, and also
> extend support to other types like boost::asio's buffer concepts as well.
>
> So my comment on your pr was asking more about specific features that denc
> requires from bufferlist, so that we could start to generalize them in a way
> that doesn't have bufferlist baked in.
>
> Thanks,
> Casey
>
> --
> To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Matt Benjamin
Red Hat, Inc.
315 West Huron Street, Suite 140A
Ann Arbor, Michigan 48103
http://www.redhat.com/en/technologies/storage
tel. 734-821-5101
fax. 734-769-8938
cel. 734-216-5309
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-15 19:30 ` Matt Benjamin
@ 2018-01-15 20:48 ` Casey Bodley
2018-01-16 11:26 ` kefu chai
0 siblings, 1 reply; 14+ messages in thread
From: Casey Bodley @ 2018-01-15 20:48 UTC (permalink / raw)
To: Matt Benjamin; +Cc: kefu chai, The Esoteric Order of the Squid Cybernetic
On 01/15/2018 02:30 PM, Matt Benjamin wrote:
> It's the buffer::raw class that abstracts foreign buffer
> representations now, is it now? A mechanism to allow seastar to
> single-allocate a composite buffer::raw and temporary_buffer<char>
> seems possible to imagine.
>
> Matt
Thanks Matt. I think that's effectively what I did with
https://github.com/cbodley/ceph/commit/67ae06e488c50a6102c66d34b942ff207493ffd6.
It allocates a buffer::raw subclass that stores temporary_buffer<char>
as a member. The raw allocation here is the same one we'd see with any
other buffer type, so I was mistaken in thinking of this as extra
overhead. The allocation in the other direction is effectively seastar's
version of this same abstraction. So I think these conversions are fine
as they are.
I do still think there are wins in generalizing denc to avoid these
conversions, but we'll have to explore whether it's worth the extra
complexity.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-15 20:48 ` Casey Bodley
@ 2018-01-16 11:26 ` kefu chai
2018-01-16 22:15 ` Casey Bodley
0 siblings, 1 reply; 14+ messages in thread
From: kefu chai @ 2018-01-16 11:26 UTC (permalink / raw)
To: Casey Bodley; +Cc: Matt Benjamin, The Esoteric Order of the Squid Cybernetic
On Tue, Jan 16, 2018 at 4:48 AM, Casey Bodley <cbodley@redhat.com> wrote:
>
> On 01/15/2018 02:30 PM, Matt Benjamin wrote:
>>
>> It's the buffer::raw class that abstracts foreign buffer
>> representations now, is it now? A mechanism to allow seastar to
>> single-allocate a composite buffer::raw and temporary_buffer<char>
>> seems possible to imagine.
>>
>> Matt
>
>
> Thanks Matt. I think that's effectively what I did with
> https://github.com/cbodley/ceph/commit/67ae06e488c50a6102c66d34b942ff207493ffd6.
> It allocates a buffer::raw subclass that stores temporary_buffer<char> as a
> member. The raw allocation here is the same one we'd see with any other
> buffer type, so I was mistaken in thinking of this as extra overhead. The
> allocation in the other direction is effectively seastar's version of this
> same abstraction. So I think these conversions are fine as they are.
>
> I do still think there are wins in generalizing denc to avoid these
> conversions, but we'll have to explore whether it's worth the extra
> complexity.
i see. is https://github.com/tchaikov/ceph/tree/wip-seastar-msg
something more close to what you are thinking about?
--
Regards
Kefu Chai
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-16 11:26 ` kefu chai
@ 2018-01-16 22:15 ` Casey Bodley
2018-01-17 12:53 ` kefu chai
0 siblings, 1 reply; 14+ messages in thread
From: Casey Bodley @ 2018-01-16 22:15 UTC (permalink / raw)
To: kefu chai; +Cc: Matt Benjamin, The Esoteric Order of the Squid Cybernetic
On 01/16/2018 06:26 AM, kefu chai wrote:
> On Tue, Jan 16, 2018 at 4:48 AM, Casey Bodley <cbodley@redhat.com> wrote:
>> On 01/15/2018 02:30 PM, Matt Benjamin wrote:
>>> It's the buffer::raw class that abstracts foreign buffer
>>> representations now, is it now? A mechanism to allow seastar to
>>> single-allocate a composite buffer::raw and temporary_buffer<char>
>>> seems possible to imagine.
>>>
>>> Matt
>>
>> Thanks Matt. I think that's effectively what I did with
>> https://github.com/cbodley/ceph/commit/67ae06e488c50a6102c66d34b942ff207493ffd6.
>> It allocates a buffer::raw subclass that stores temporary_buffer<char> as a
>> member. The raw allocation here is the same one we'd see with any other
>> buffer type, so I was mistaken in thinking of this as extra overhead. The
>> allocation in the other direction is effectively seastar's version of this
>> same abstraction. So I think these conversions are fine as they are.
>>
>> I do still think there are wins in generalizing denc to avoid these
>> conversions, but we'll have to explore whether it's worth the extra
>> complexity.
> i see. is https://github.com/tchaikov/ceph/tree/wip-seastar-msg
> something more close to what you are thinking about?
>
Dear Kefu, you are a wizard. That looks like a great start!
I'm guessing that segmented buffers will be the hard part - we might
look to the boost::asio buffer concepts for some ideas there?
they have const and non-const sequences:
http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/ConstBufferSequence.html
http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/MutableBufferSequence.html
and a dynamic/resizable sequence:
http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/DynamicBuffer.htm
Boost has lots of built-in adapters for array/vector/string types:
http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/buffer.html
If we could find a way to use those concepts directly, we'd get those
built-in types for free, and it should be easy to adapt other types like
those from seastar.
DynamicBuffer::prepare() looks like a natural way to do the append part
on encode, but it returns a MutableBufferSequence so is not guaranteed
to be contiguous. Can you remind me where we really depend on contiguous
buffers? Is it just that some types set need_contiguous=false because we
haven't yet implemented logic for segmented buffers, or are there cases
where implementing that logic is actually intractable?
Thanks,
Casey
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-16 22:15 ` Casey Bodley
@ 2018-01-17 12:53 ` kefu chai
2018-01-17 13:13 ` Matt Benjamin
2018-01-18 16:35 ` Casey Bodley
0 siblings, 2 replies; 14+ messages in thread
From: kefu chai @ 2018-01-17 12:53 UTC (permalink / raw)
To: Casey Bodley; +Cc: Matt Benjamin, The Esoteric Order of the Squid Cybernetic
On Wed, Jan 17, 2018 at 6:15 AM, Casey Bodley <cbodley@redhat.com> wrote:
>
> On 01/16/2018 06:26 AM, kefu chai wrote:
>>
>> On Tue, Jan 16, 2018 at 4:48 AM, Casey Bodley <cbodley@redhat.com> wrote:
>>>
>>> On 01/15/2018 02:30 PM, Matt Benjamin wrote:
>>>>
>>>> It's the buffer::raw class that abstracts foreign buffer
>>>> representations now, is it now? A mechanism to allow seastar to
>>>> single-allocate a composite buffer::raw and temporary_buffer<char>
>>>> seems possible to imagine.
>>>>
>>>> Matt
>>>
>>>
>>> Thanks Matt. I think that's effectively what I did with
>>>
>>> https://github.com/cbodley/ceph/commit/67ae06e488c50a6102c66d34b942ff207493ffd6.
>>> It allocates a buffer::raw subclass that stores temporary_buffer<char> as
>>> a
>>> member. The raw allocation here is the same one we'd see with any other
>>> buffer type, so I was mistaken in thinking of this as extra overhead. The
>>> allocation in the other direction is effectively seastar's version of
>>> this
>>> same abstraction. So I think these conversions are fine as they are.
>>>
>>> I do still think there are wins in generalizing denc to avoid these
>>> conversions, but we'll have to explore whether it's worth the extra
>>> complexity.
>>
>> i see. is https://github.com/tchaikov/ceph/tree/wip-seastar-msg
>> something more close to what you are thinking about?
>>
>
> Dear Kefu, you are a wizard. That looks like a great start!
>
> I'm guessing that segmented buffers will be the hard part - we might look to
> the boost::asio buffer concepts for some ideas there?
>
> they have const and non-const sequences:
> http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/ConstBufferSequence.html
> http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/MutableBufferSequence.html
>
> and a dynamic/resizable sequence:
> http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/DynamicBuffer.htm
>
> Boost has lots of built-in adapters for array/vector/string types:
> http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/buffer.html
>
> If we could find a way to use those concepts directly, we'd get those
> built-in types for free, and it should be easy to adapt other types like
> those from seastar.
i think it could be feasible to come up with some generic adapter to
use these concepts, but we might need to focus on some typical use
cases. for example, to encode and write a MOSDOpReply:
assuming that we want to encode it into multiple temporary buffers and
send them using a seastar::packet. the MOSDOpReply struct has a field
of vector<OSDOp>, and OSDOp in turn has "bufferlist outdata;" in it.
for a read op, apparently, we want to avoid memcpy. if the underlying
read(store) returns a bufferlist, the encoder should be able to
shallow copy the bufferlist and encapsulate it in a fragment with a
customized deleter or just a temporary_buffer. if we want to avoid the
conversion from buffer::list to seastar::packet, probably we should
generalize the appender so it
- is able to manage the life cycle of the buffers in bufferlist being
encoded. i.e. should flush current temporary_buffer, and translate all
buffer::ptr to seastar::temporary_buffer, then append them to the
output seastar::packet
- just writes to the local temporary_buffer directly when encoding
other kinds of objects.
so, i don't think we can have a very generic appender if we want to be
efficient. but we can define one which works for certain output type.
in this example, it's seastar::packet.
>
> DynamicBuffer::prepare() looks like a natural way to do the append part on
> encode, but it returns a MutableBufferSequence so is not guaranteed to be
> contiguous. Can you remind me where we really depend on contiguous buffers?
IIRC, we don't really depend on contiguous buffers. but we do expect
that the buffer we are manipulating is continuous, so we can have the
opportunity to optimize the dencoder:
- encoding: it's a noticeable overhead to check the underlying buffer
boundary when writing to a buffer. that's why we introduced the
appender to facilitate the encoding. see [1]
- decoding: for the similar reason, it's more performant to just read
a contiguous buffer than reading from a segmented one. in other words,
if we can ensure a the bufferlist being decoded has only a single raw
buffer, why bother checking the boundary?
if we want to encode object into the mutable buffers returned
DynamicBuffer::prepare(), we need to check x.size() when writing to
x.data() and move on to the next one if current buffer chunk is too
small.
--
[1] https://www.spinics.net/lists/ceph-devel/msg32608.html
> Is it just that some types set need_contiguous=false because we haven't yet
> implemented logic for segmented buffers, or are there cases where
> implementing that logic is actually intractable?
"need_contiguous" trait was added to the denc for the case where the
buffer being decoded are large objects and they could be segmented.
these objects are read from bluestore. but i think we would expand the
case to the large message if we rebuild/flatten the segmented buffer,
the overhead of reallocating the buffer and memcpy calls offsets the
performance improvement we achieve by avoiding the bound check and
simpler logic. before that, we always do the rebuild before decoding a
buffer::list::iterator.
>
> Thanks,
> Casey
--
Regards
Kefu Chai
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-17 12:53 ` kefu chai
@ 2018-01-17 13:13 ` Matt Benjamin
2018-01-17 15:42 ` kefu chai
2018-01-18 16:35 ` Casey Bodley
1 sibling, 1 reply; 14+ messages in thread
From: Matt Benjamin @ 2018-01-17 13:13 UTC (permalink / raw)
To: kefu chai; +Cc: Casey Bodley, The Esoteric Order of the Squid Cybernetic
On Wed, Jan 17, 2018 at 7:53 AM, kefu chai <tchaikov@gmail.com> wrote:
>
> i think it could be feasible to come up with some generic adapter to
> use these concepts, but we might need to focus on some typical use
> cases. for example, to encode and write a MOSDOpReply:
>
> assuming that we want to encode it into multiple temporary buffers and
> send them using a seastar::packet. the MOSDOpReply struct has a field
> of vector<OSDOp>, and OSDOp in turn has "bufferlist outdata;" in it.
> for a read op, apparently, we want to avoid memcpy. if the underlying
> read(store) returns a bufferlist, the encoder should be able to
> shallow copy the bufferlist and encapsulate it in a fragment with a
> customized deleter or just a temporary_buffer. if we want to avoid the
> conversion from buffer::list to seastar::packet, probably we should
> generalize the appender so it
Yes, we'd like to avoid such copies.
>
> - is able to manage the life cycle of the buffers in bufferlist being
> encoded. i.e. should flush current temporary_buffer, and translate all
> buffer::ptr to seastar::temporary_buffer, then append them to the
> output seastar::packet
> - just writes to the local temporary_buffer directly when encoding
> other kinds of objects.
>
> so, i don't think we can have a very generic appender if we want to be
> efficient. but we can define one which works for certain output type.
> in this example, it's seastar::packet.
That sounds right to me.
>
>>
>> DynamicBuffer::prepare() looks like a natural way to do the append part on
>> encode, but it returns a MutableBufferSequence so is not guaranteed to be
>> contiguous. Can you remind me where we really depend on contiguous buffers?
>
> IIRC, we don't really depend on contiguous buffers. but we do expect
> that the buffer we are manipulating is continuous, so we can have the
> opportunity to optimize the dencoder:
>
> - encoding: it's a noticeable overhead to check the underlying buffer
> boundary when writing to a buffer. that's why we introduced the
> appender to facilitate the encoding. see [1]
This is kind of surprising.
> - decoding: for the similar reason, it's more performant to just read
> a contiguous buffer than reading from a segmented one. in other words,
> if we can ensure a the bufferlist being decoded has only a single raw
> buffer, why bother checking the boundary?
Is that likely? If the decoding case is from seastar, isn't the
incoming data likely to be in the form of several mbufs?
>
> if we want to encode object into the mutable buffers returned
> DynamicBuffer::prepare(), we need to check x.size() when writing to
> x.data() and move on to the next one if current buffer chunk is too
> small.
>
> --
> [1] https://www.spinics.net/lists/ceph-devel/msg32608.html
>
>
>> Is it just that some types set need_contiguous=false because we haven't yet
>> implemented logic for segmented buffers, or are there cases where
>> implementing that logic is actually intractable?
>
> "need_contiguous" trait was added to the denc for the case where the
> buffer being decoded are large objects and they could be segmented.
> these objects are read from bluestore. but i think we would expand the
> case to the large message if we rebuild/flatten the segmented buffer,
> the overhead of reallocating the buffer and memcpy calls offsets the
> performance improvement we achieve by avoiding the bound check and
> simpler logic. before that, we always do the rebuild before decoding a
> buffer::list::iterator.
That's what I would have expected.
>
>>
>> Thanks,
>> Casey
>
>
>
> --
> Regards
> Kefu Chai
--
Matt Benjamin
Red Hat, Inc.
315 West Huron Street, Suite 140A
Ann Arbor, Michigan 48103
http://www.redhat.com/en/technologies/storage
tel. 734-821-5101
fax. 734-769-8938
cel. 734-216-5309
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-17 13:13 ` Matt Benjamin
@ 2018-01-17 15:42 ` kefu chai
0 siblings, 0 replies; 14+ messages in thread
From: kefu chai @ 2018-01-17 15:42 UTC (permalink / raw)
To: Matt Benjamin; +Cc: Casey Bodley, The Esoteric Order of the Squid Cybernetic
On Wed, Jan 17, 2018 at 9:13 PM, Matt Benjamin <mbenjami@redhat.com> wrote:
> On Wed, Jan 17, 2018 at 7:53 AM, kefu chai <tchaikov@gmail.com> wrote:
>>
>> i think it could be feasible to come up with some generic adapter to
>> use these concepts, but we might need to focus on some typical use
>> cases. for example, to encode and write a MOSDOpReply:
>>
>> assuming that we want to encode it into multiple temporary buffers and
>> send them using a seastar::packet. the MOSDOpReply struct has a field
>> of vector<OSDOp>, and OSDOp in turn has "bufferlist outdata;" in it.
>> for a read op, apparently, we want to avoid memcpy. if the underlying
>> read(store) returns a bufferlist, the encoder should be able to
>> shallow copy the bufferlist and encapsulate it in a fragment with a
>> customized deleter or just a temporary_buffer. if we want to avoid the
>> conversion from buffer::list to seastar::packet, probably we should
>> generalize the appender so it
>
> Yes, we'd like to avoid such copies.
>
>>
>> - is able to manage the life cycle of the buffers in bufferlist being
>> encoded. i.e. should flush current temporary_buffer, and translate all
>> buffer::ptr to seastar::temporary_buffer, then append them to the
>> output seastar::packet
>> - just writes to the local temporary_buffer directly when encoding
>> other kinds of objects.
>>
>> so, i don't think we can have a very generic appender if we want to be
>> efficient. but we can define one which works for certain output type.
>> in this example, it's seastar::packet.
>
> That sounds right to me.
>
>>
>>>
>>> DynamicBuffer::prepare() looks like a natural way to do the append part on
>>> encode, but it returns a MutableBufferSequence so is not guaranteed to be
>>> contiguous. Can you remind me where we really depend on contiguous buffers?
>>
>> IIRC, we don't really depend on contiguous buffers. but we do expect
>> that the buffer we are manipulating is continuous, so we can have the
>> opportunity to optimize the dencoder:
>>
>> - encoding: it's a noticeable overhead to check the underlying buffer
>> boundary when writing to a buffer. that's why we introduced the
>> appender to facilitate the encoding. see [1]
>
> This is kind of surprising.
forgot to mention, preallocated buffer also avoid the possible
overhead to allocate multiple new buffers when encoding progresses.
>
>> - decoding: for the similar reason, it's more performant to just read
>> a contiguous buffer than reading from a segmented one. in other words,
>> if we can ensure a the bufferlist being decoded has only a single raw
>> buffer, why bother checking the boundary?
>
> Is that likely? If the decoding case is from seastar, isn't the
> incoming data likely to be in the form of several mbufs?
>
>>
>> if we want to encode object into the mutable buffers returned
>> DynamicBuffer::prepare(), we need to check x.size() when writing to
>> x.data() and move on to the next one if current buffer chunk is too
>> small.
>>
>> --
>> [1] https://www.spinics.net/lists/ceph-devel/msg32608.html
>>
>>
>>> Is it just that some types set need_contiguous=false because we haven't yet
>>> implemented logic for segmented buffers, or are there cases where
>>> implementing that logic is actually intractable?
>>
>> "need_contiguous" trait was added to the denc for the case where the
>> buffer being decoded are large objects and they could be segmented.
>> these objects are read from bluestore. but i think we would expand the
>> case to the large message if we rebuild/flatten the segmented buffer,
>> the overhead of reallocating the buffer and memcpy calls offsets the
>> performance improvement we achieve by avoiding the bound check and
>> simpler logic. before that, we always do the rebuild before decoding a
>> buffer::list::iterator.
>
> That's what I would have expected.
>
>>
>>>
>>> Thanks,
>>> Casey
>>
>>
>>
>> --
>> Regards
>> Kefu Chai
>
>
>
> --
>
> Matt Benjamin
> Red Hat, Inc.
> 315 West Huron Street, Suite 140A
> Ann Arbor, Michigan 48103
>
> http://www.redhat.com/en/technologies/storage
>
> tel. 734-821-5101
> fax. 734-769-8938
> cel. 734-216-5309
--
Regards
Kefu Chai
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: seastar temporary_buffer/packet and ceph::buffer
2018-01-17 12:53 ` kefu chai
2018-01-17 13:13 ` Matt Benjamin
@ 2018-01-18 16:35 ` Casey Bodley
1 sibling, 0 replies; 14+ messages in thread
From: Casey Bodley @ 2018-01-18 16:35 UTC (permalink / raw)
To: kefu chai; +Cc: Matt Benjamin, The Esoteric Order of the Squid Cybernetic
On 01/17/2018 07:53 AM, kefu chai wrote:
> On Wed, Jan 17, 2018 at 6:15 AM, Casey Bodley <cbodley@redhat.com> wrote:
>> On 01/16/2018 06:26 AM, kefu chai wrote:
>>> On Tue, Jan 16, 2018 at 4:48 AM, Casey Bodley <cbodley@redhat.com> wrote:
>>>> On 01/15/2018 02:30 PM, Matt Benjamin wrote:
>>>>> It's the buffer::raw class that abstracts foreign buffer
>>>>> representations now, is it now? A mechanism to allow seastar to
>>>>> single-allocate a composite buffer::raw and temporary_buffer<char>
>>>>> seems possible to imagine.
>>>>>
>>>>> Matt
>>>>
>>>> Thanks Matt. I think that's effectively what I did with
>>>>
>>>> https://github.com/cbodley/ceph/commit/67ae06e488c50a6102c66d34b942ff207493ffd6.
>>>> It allocates a buffer::raw subclass that stores temporary_buffer<char> as
>>>> a
>>>> member. The raw allocation here is the same one we'd see with any other
>>>> buffer type, so I was mistaken in thinking of this as extra overhead. The
>>>> allocation in the other direction is effectively seastar's version of
>>>> this
>>>> same abstraction. So I think these conversions are fine as they are.
>>>>
>>>> I do still think there are wins in generalizing denc to avoid these
>>>> conversions, but we'll have to explore whether it's worth the extra
>>>> complexity.
>>> i see. is https://github.com/tchaikov/ceph/tree/wip-seastar-msg
>>> something more close to what you are thinking about?
>>>
>> Dear Kefu, you are a wizard. That looks like a great start!
>>
>> I'm guessing that segmented buffers will be the hard part - we might look to
>> the boost::asio buffer concepts for some ideas there?
>>
>> they have const and non-const sequences:
>> http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/ConstBufferSequence.html
>> http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/MutableBufferSequence.html
>>
>> and a dynamic/resizable sequence:
>> http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/DynamicBuffer.htm
>>
>> Boost has lots of built-in adapters for array/vector/string types:
>> http://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/reference/buffer.html
>>
>> If we could find a way to use those concepts directly, we'd get those
>> built-in types for free, and it should be easy to adapt other types like
>> those from seastar.
> i think it could be feasible to come up with some generic adapter to
> use these concepts, but we might need to focus on some typical use
> cases. for example, to encode and write a MOSDOpReply:
>
> assuming that we want to encode it into multiple temporary buffers and
> send them using a seastar::packet. the MOSDOpReply struct has a field
> of vector<OSDOp>, and OSDOp in turn has "bufferlist outdata;" in it.
> for a read op, apparently, we want to avoid memcpy. if the underlying
> read(store) returns a bufferlist, the encoder should be able to
> shallow copy the bufferlist and encapsulate it in a fragment with a
> customized deleter or just a temporary_buffer. if we want to avoid the
> conversion from buffer::list to seastar::packet, probably we should
> generalize the appender so it
>
> - is able to manage the life cycle of the buffers in bufferlist being
> encoded. i.e. should flush current temporary_buffer, and translate all
> buffer::ptr to seastar::temporary_buffer, then append them to the
> output seastar::packet
> - just writes to the local temporary_buffer directly when encoding
> other kinds of objects.
>
> so, i don't think we can have a very generic appender if we want to be
> efficient. but we can define one which works for certain output type.
> in this example, it's seastar::packet.
That example helps a lot. The asio buffer concepts aren't a good fit
here because they don't capture our zero-copy requirements or any of the
ownership/sharing stuff that goes along with that.
I really like how your approach only pays for the
bufferptr->temporary_buffer conversions where we actually need that
sharing, and not in the common encode case.
>> DynamicBuffer::prepare() looks like a natural way to do the append part on
>> encode, but it returns a MutableBufferSequence so is not guaranteed to be
>> contiguous. Can you remind me where we really depend on contiguous buffers?
> IIRC, we don't really depend on contiguous buffers. but we do expect
> that the buffer we are manipulating is continuous, so we can have the
> opportunity to optimize the dencoder:
>
> - encoding: it's a noticeable overhead to check the underlying buffer
> boundary when writing to a buffer. that's why we introduced the
> appender to facilitate the encoding. see [1]
> - decoding: for the similar reason, it's more performant to just read
> a contiguous buffer than reading from a segmented one. in other words,
> if we can ensure a the bufferlist being decoded has only a single raw
> buffer, why bother checking the boundary?
>
> if we want to encode object into the mutable buffers returned
> DynamicBuffer::prepare(), we need to check x.size() when writing to
> x.data() and move on to the next one if current buffer chunk is too
> small.
>
> --
> [1] https://www.spinics.net/lists/ceph-devel/msg32608.html
Okay, thanks Kefu. I had managed to forget most of that.
>
>> Is it just that some types set need_contiguous=false because we haven't yet
>> implemented logic for segmented buffers, or are there cases where
>> implementing that logic is actually intractable?
> "need_contiguous" trait was added to the denc for the case where the
> buffer being decoded are large objects and they could be segmented.
> these objects are read from bluestore. but i think we would expand the
> case to the large message if we rebuild/flatten the segmented buffer,
> the overhead of reallocating the buffer and memcpy calls offsets the
> performance improvement we achieve by avoiding the bound check and
> simpler logic. before that, we always do the rebuild before decoding a
> buffer::list::iterator.
>
>> Thanks,
>> Casey
>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2018-01-18 16:35 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-01-15 15:49 seastar temporary_buffer/packet and ceph::buffer kefu chai
2018-01-15 16:53 ` kefu chai
2018-01-15 17:04 ` Piotr Dałek
2018-01-15 17:09 ` kefu chai
2018-01-15 17:13 ` Piotr Dałek
2018-01-15 17:19 ` Casey Bodley
2018-01-15 19:30 ` Matt Benjamin
2018-01-15 20:48 ` Casey Bodley
2018-01-16 11:26 ` kefu chai
2018-01-16 22:15 ` Casey Bodley
2018-01-17 12:53 ` kefu chai
2018-01-17 13:13 ` Matt Benjamin
2018-01-17 15:42 ` kefu chai
2018-01-18 16:35 ` Casey Bodley
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.