Date: Tue, 23 Oct 2001 14:03:19 -0700 From: Luigi Rizzo <rizzo@aciri.org> To: Garrett Wollman <wollman@khavrinen.lcs.mit.edu> Cc: net@FreeBSD.ORG Subject: Re: performance issues with M_PREPEND on clusters Message-ID: <20011023140318.A35869@iguana.aciri.org> In-Reply-To: <200110231917.f9NJH4T32996@khavrinen.lcs.mit.edu> References: <20011023110307.A34494@iguana.aciri.org> <200110231917.f9NJH4T32996@khavrinen.lcs.mit.edu>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, Oct 23, 2001 at 03:17:04PM -0400, Garrett Wollman wrote:
> <<On Tue, 23 Oct 2001 11:03:07 -0700, Luigi Rizzo <rizzo@aciri.org> said:
>
> > Similar things could be done in m_pullup() to avoid the
> > extra allocation.
>
> Can't be done in m_pullup: the whole purpose of m_pullup is to
> *guarantee* that the data in question will never be shared. It might
> be worth having a new interface which doesn't provide such a
> guarantee.
You are right, we cannot change the semantics of m_pullup() without
carefully analysing how it is used, and this definitely calls for
one or two new interfaces (m_pullup_readonly(), m_pullup_writable()).
Technically, it is correct that m_pullup guarantees that the data
in question will never be shared, but it seems to me more an artifact
of its implementation than a real goal.
From what i see, m_pullup() is mostly used to make sure that a
block is contiguous, and in some other cases to have a writable
copy of the block. In both cases being able to write into the
cluster would save a bit of work.
Yes, there are situations (e.g. where you are replicating a packet
and changing some things in the header for each replica -- see
EXAMPLE 1) where the current semantics of m_pullup() _seems_ to
save something, but this comes at the price of an m_copy() so there
is really no saving compared to EXAMPLE 2.
By having the new m_pullup_XXX() calls, you could rewrite the same
code as in EXAMPLE 3, with the advantage that the first instance
could turn into a no-op, and you replicate only if really necessary.
cheers
luigi
-----------------------------------------------------------------
EXAMPLE 1: /* some pieces of the kernel are like this */
m = m_pullup(m, some_len);
for (;;) {
<change something in the private part of m>
n = m_copy(m, 0, M_COPYALL);
<pass n around>
if (some_condition)
break ;
}
m_free(m);
EXAMPLE 2: /* they could be rewritten in this way */
canfree = 1;
for (;;) {
n = m_pullup(m, some_len);
if (n == m)
canfree=0;
<change something in the private part of n>
<pass n around>
if (some_condition)
break ;
}
if (canfree)
m_free(m);
EXAMPLE 3: /* or in this way with a new m_pullupXXX() interface */
for (;;) {
n = m_pullup_writable(m, some_len);
if (n == m)
canfree=0;
<change something in n>
<pass n around>
if (some_condition)
break ;
}
if (canfree)
m_free(m);
----------------------------------+-----------------------------------------
Luigi RIZZO, luigi@iet.unipi.it . ACIRI/ICSI (on leave from Univ. di Pisa)
http://www.iet.unipi.it/~luigi/ . 1947 Center St, Berkeley CA 94704
Phone: (510) 666 2927
----------------------------------+-----------------------------------------
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20011023140318.A35869>
