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>