Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 16 Mar 2002 12:21:44 +0000
From:      Tony Finch <dot@dotat.at>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        fanf@chiark.greenend.org.uk, dfr@FreeBSD.org
Subject:   kern/35978: improve kobj method dispatch
Message-ID:  <E16mDBw-0003rH-00@hand.dotat.at>

next in thread | raw e-mail | index | archive | help

>Number:         35978
>Category:       kern
>Synopsis:       improve kobj method dispatch
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sat Mar 16 04:30:06 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Tony Finch
>Release:        FreeBSD 4.5-STABLE-20020312 i386
>Organization:
dotat labs
>Environment:
System: FreeBSD hand.dotat.at 4.5-STABLE-20020312 FreeBSD 4.5-STABLE-20020312 #19: Tue Mar 12 13:45:49 GMT 2002 fanf@hand.dotat.at:/FreeBSD/obj/FreeBSD/releng4/sys/SHARP i386

>Description:

The patch below improves kobj method dispatch in two ways:
(1) It removes a load from the critical path;
(2) It reduces the size of the inlined code in the slow path.

Removing the load reduces method dispatch time by 5% in the fast
case (from 33% slower than a normal function call to 27% slower).
In the statistics below: 0 is a normal C function call and return;
1 is the current kobj method dispatch; 2 has the load removed from
the fast case; 3 also has the smaller slow case; and 4 has an
alternative slow case designed to allow better optimisation by the
compiler.

min/ave/max 16.313 / 17.299 / 18.169  stddev 0.6775  0
min/ave/max 21.419 / 22.009 / 35.616  stddev 0.9760  2
min/ave/max 21.398 / 22.028 / 34.887  stddev 0.6457  3
min/ave/max 21.421 / 22.116 / 34.535  stddev 0.7643  4
min/ave/max 21.967 / 23.105 / 34.275  stddev 0.7572  1

The load is removed by changing the cache index to use the address
of the method descriptor rather than an ID number inside the
descriptor. The new code looks nasty but compiles down to just a
mask and an indexed load; the sizeof business ensures that shifting
isn't needed.

The reduction in code size comes from removing an argument from
kobj_lookup_method(). This adds up to over 600 bytes reduction in
-STABLE's LINT.

This change preserves binary compatibility with the old code, but
if that is not needed then all the method registration stuff can
be removed from subr_kobj.c and the id field can be removed from
struct kobjop_desc.

>How-To-Repeat:

I have a simple benchmarking program which I can provide if anyone
is interested.

>Fix:

--- /usr/src/sys/sys/kobj.h	2 Feb 2001 19:49:14 -0000	1.5.2.1
+++ /usr/src/sys/sys/kobj.h	16 Mar 2002 03:19:50 -0000
@@ -146,24 +146,33 @@
 #endif
 
 /*
+ * Get the cache entry corresponding to a method descriptor.
+ */
+#define KOBJ_CACHE_ENTRY(OPS,DESC) \
+    (&(OPS)->cache[(int)(DESC) / sizeof(kobj_method_t) % KOBJ_CACHE_SIZE])
+
+/*
  * Lookup the method in the cache and if it isn't there look it up the
  * slow way.
  */
 #define KOBJOPLOOKUP(OPS,OP) do {					\
 	kobjop_desc_t _desc = &OP##_##desc;				\
-	kobj_method_t *_ce =						\
-	    &OPS->cache[_desc->id & (KOBJ_CACHE_SIZE-1)];		\
+	kobj_method_t *_ce = KOBJ_CACHE_ENTRY(OPS,_desc);		\
 	if (_ce->desc != _desc) {					\
 		KOBJOPMISS;						\
-		kobj_lookup_method(OPS->cls->methods, _ce, _desc);	\
+		kobj_lookup_method2(OPS, _desc);			\
 	} else {							\
 		KOBJOPHIT;						\
 	}								\
 	_m = _ce->func;							\
 } while(0)
 
+/* old API for binary compatibity */
 void kobj_lookup_method(kobj_method_t *methods,
 			kobj_method_t *ce,
 			kobjop_desc_t desc);
+
+/* new API for more compact code */
+void kobj_lookup_method2(kobj_ops_t ops, kobjop_desc_t desc);
 
 #endif /* !_SYS_KOBJ_H_ */
--- /usr/src/sys/kern/subr_kobj.c	2 Feb 2001 19:49:13 -0000	1.4.2.1
+++ /usr/src/sys/kern/subr_kobj.c	16 Mar 2002 03:07:27 -0000
@@ -147,6 +147,13 @@
 }
 
 void
+kobj_lookup_method2(kobj_ops_t ops, kobjop_desc_t desc)
+{
+	kobj_method_t *ce = KOBJ_CACHE_ENTRY(ops,desc);
+	kobj_lookup_method(ops->cls->methods, ce, desc);
+}
+
+void
 kobj_class_free(kobj_class_t cls)
 {
 	int i;
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E16mDBw-0003rH-00>