From: Hiro Yoshioka <lkml.hyoshiok@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Hiro Yoshioka <hyoshiok@miraclelinux.com>
Subject: [RFC] [PATCH] cache pollution aware __copy_from_user_ll()
Date: Sun, 14 Aug 2005 18:16:00 +0900 [thread overview]
Message-ID: <98df96d305081402164ce52f8@mail.gmail.com> (raw)
Hi,
The following is a patch to reduce a cache pollution
of __copy_from_user_ll().
When I run simple iozone benchmark to find a performance bottleneck of
the linux kernel, I found that __copy_from_user_ll() spent CPU cycle
most and it did many cache misses.
The following is profiled by oprofile.
Top 5 CPU cycle
CPU: P4 / Xeon, speed 2200.91 MHz (estimated)
Counted GLOBAL_POWER_EVENTS events (time during which processor is not
stopped) with a unit mask of 0x01 (mandatory) count 100000
samples % app name symbol name
281538 15.2083 vmlinux __copy_from_user_ll
81069 4.3792 vmlinux _spin_lock
75523 4.0796 vmlinux journal_add_journal_head
63674 3.4396 vmlinux do_get_write_access
52634 2.8432 vmlinux journal_put_journal_head
(pattern9-0-cpu4-0-08141700/summary.out)
Top 5 Memory Access and Cache miss
CPU: P4 / Xeon, speed 2200.91 MHz (estimated)
Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus
unit) with a unit mask of 0x3f (multiple flags) count 3000
Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus
unit) with a unit mask of 0x200 (read 3rd level cache miss) count 3000
samples % samples % app name symbol name
120801 7.4379 37017 63.4603 vmlinux __copy_from_user_ll
84139 5.1806 885 1.5172 vmlinux _spin_lock
66027 4.0654 656 1.1246 vmlinux
journal_add_journal_head
60400 3.7189 250 0.4286 vmlinux __find_get_block
60032 3.6963 120 0.2057 vmlinux
journal_dirty_metadata
__copy_from_user_ll spent 63.4603% of L3 cache miss though it spent only
7.4379% of memory access.
In order to reduce the cache miss in the __copy_from_user_ll, I made
the following patch and confirmed the reduction of the miss.
Top 5 CPU cycle
CPU: P4 / Xeon, speed 2200.93 MHz (estimated)
Counted GLOBAL_POWER_EVENTS events (time during which processor is not
stopped) with a unit mask of 0x01 (mandatory) count 100000
samples % app name symbol name
120717 8.3454 vmlinux _mmx_memcpy_nt
65955 4.5596 vmlinux do_get_write_access
56088 3.8775 vmlinux journal_put_journal_head
52550 3.6329 vmlinux journal_dirty_metadata
38886 2.6883 vmlinux journal_add_journal_head
pattern9-0-cpu4-0-08141627/summary.out
_mmx_memcpy_nt is the new function which is called from
__copy_from_user_ll and it spent only 42.88% of the original
implementation. (120717/281538==42.88%)
Top 5 Memory Access
CPU: P4 / Xeon, speed 2200.93 MHz (estimated)
Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus
unit) with a unit mask of 0x3f (multiple flags) count 3000
Counted BSQ_CACHE_REFERENCE events (cache references seen by the bus
unit) with a unit mask of 0x200 (read 3rd level cache miss) count 3000
samples % samples % app name symbol name
90918 6.3079 89 0.5673 vmlinux _mmx_memcpy_nt
83654 5.8039 177 1.1283 vmlinux
journal_dirty_metadata
57836 4.0127 348 2.2183 vmlinux
journal_put_journal_head
48236 3.3466 165 1.0518 vmlinux do_get_write_access
44546 3.0906 21 0.1339 vmlinux __getblk
The cache miss reduced from 37017 (63.4603%) to 89 (0.5673%). It is
0.24% of the original implementation.
The actual elapse time which five times run were 229.76 (sec) and
222.94 (sec). (229.76/222.94= 3.06% gain)
iozone -CMR -i 0 -+n -+u -s 8000MB -t 4
What do you think?
--- linux-2.6.12.4.orig/arch/i386/lib/usercopy.c 2005-08-05
16:04:37.000000000 +0900
+++ linux-2.6.12.4/arch/i386/lib/usercopy.c 2005-08-12 13:18:14.106916200 +0900
@@ -10,6 +10,7 @@
#include <linux/highmem.h>
#include <linux/blkdev.h>
#include <linux/module.h>
+#include <asm/i387.h>
#include <asm/uaccess.h>
#include <asm/mmx.h>
@@ -511,6 +512,108 @@
: "memory"); \
} while (0)
+/* Non Temporal Hint version of mmx_memcpy */
+/* It is cache aware */
+/* hyoshiok@miraclelinux.com */
+static unsigned long _mmx_memcpy_nt(void *to, const void *from, size_t len)
+{
+ /* Note! gcc doesn't seem to align stack variables properly, so we
+ * need to make use of unaligned loads and stores.
+ */
+ void *p;
+ int i;
+
+ if (unlikely(in_interrupt())){
+ __copy_user_zeroing(to, from, len);
+ return len;
+ }
+
+ p = to;
+ i = len >> 6; /* len/64 */
+
+ kernel_fpu_begin();
+
+ __asm__ __volatile__ (
+ "1: prefetchnta (%0)\n" /* This set is 28 bytes */
+ " prefetchnta 64(%0)\n"
+ " prefetchnta 128(%0)\n"
+ " prefetchnta 192(%0)\n"
+ " prefetchnta 256(%0)\n"
+ "2: \n"
+ ".section .fixup, \"ax\"\n"
+ "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
+ " jmp 2b\n"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 1b, 3b\n"
+ ".previous"
+ : : "r" (from) );
+
+ for(; i>5; i--)
+ {
+ __asm__ __volatile__ (
+ "1: prefetchnta 320(%0)\n"
+ "2: movq (%0), %%mm0\n"
+ " movq 8(%0), %%mm1\n"
+ " movq 16(%0), %%mm2\n"
+ " movq 24(%0), %%mm3\n"
+ " movntq %%mm0, (%1)\n"
+ " movntq %%mm1, 8(%1)\n"
+ " movntq %%mm2, 16(%1)\n"
+ " movntq %%mm3, 24(%1)\n"
+ " movq 32(%0), %%mm0\n"
+ " movq 40(%0), %%mm1\n"
+ " movq 48(%0), %%mm2\n"
+ " movq 56(%0), %%mm3\n"
+ " movntq %%mm0, 32(%1)\n"
+ " movntq %%mm1, 40(%1)\n"
+ " movntq %%mm2, 48(%1)\n"
+ " movntq %%mm3, 56(%1)\n"
+ ".section .fixup, \"ax\"\n"
+ "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
+ " jmp 2b\n"
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .long 1b, 3b\n"
+ ".previous"
+ : : "r" (from), "r" (to) : "memory");
+ from+=64;
+ to+=64;
+ }
+
+ for(; i>0; i--)
+ {
+ __asm__ __volatile__ (
+ " movq (%0), %%mm0\n"
+ " movq 8(%0), %%mm1\n"
+ " movq 16(%0), %%mm2\n"
+ " movq 24(%0), %%mm3\n"
+ " movntq %%mm0, (%1)\n"
+ " movntq %%mm1, 8(%1)\n"
+ " movntq %%mm2, 16(%1)\n"
+ " movntq %%mm3, 24(%1)\n"
+ " movq 32(%0), %%mm0\n"
+ " movq 40(%0), %%mm1\n"
+ " movq 48(%0), %%mm2\n"
+ " movq 56(%0), %%mm3\n"
+ " movntq %%mm0, 32(%1)\n"
+ " movntq %%mm1, 40(%1)\n"
+ " movntq %%mm2, 48(%1)\n"
+ " movntq %%mm3, 56(%1)\n"
+ : : "r" (from), "r" (to) : "memory");
+ from+=64;
+ to+=64;
+ }
+ /*
+ * Now do the tail of the block
+ */
+ kernel_fpu_end();
+ if(i=(len&63))
+ __copy_user_zeroing(to, from, i);
+ return i;
+}
unsigned long __copy_to_user_ll(void __user *to, const void *from,
unsigned long n)
{
@@ -575,10 +678,14 @@
__copy_from_user_ll(void *to, const void __user *from, unsigned long n)
{
BUG_ON((long)n < 0);
- if (movsl_is_ok(to, from, n))
+ if (n < 512) {
+ if (movsl_is_ok(to, from, n))
__copy_user_zeroing(to, from, n);
- else
+ else
n = __copy_user_zeroing_intel(to, from, n);
+ }
+ else
+ n = _mmx_memcpy_nt(to, from, n);
return n;
}
Thanks in advance,
Hiro
--
hyoshiok at miraclelinux.com
next reply other threads:[~2005-08-14 9:16 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-08-14 9:16 Hiro Yoshioka [this message]
2005-08-14 9:41 ` [RFC] [PATCH] cache pollution aware __copy_from_user_ll() Arjan van de Ven
2005-08-14 10:22 ` Hiro Yoshioka
2005-08-14 10:35 ` Arjan van de Ven
2005-08-14 10:45 ` Christoph Hellwig
2005-08-15 6:43 ` Hiro Yoshioka
2005-08-15 7:16 ` Arjan van de Ven
2005-08-15 8:44 ` Hiro Yoshioka
2005-08-15 8:53 ` Arjan van de Ven
2005-08-15 23:33 ` Hiro Yoshioka
2005-08-16 3:30 ` Hiro Yoshioka
2005-08-16 4:17 ` Hirokazu Takahashi
2005-08-16 4:54 ` Hiro Yoshioka
2005-08-16 5:43 ` Arjan van de Ven
2005-08-16 10:16 ` Hiro Yoshioka
2005-08-16 10:19 ` Hirokazu Takahashi
2005-08-16 10:25 ` Arjan van de Ven
2005-08-16 10:24 ` Hirokazu Takahashi
2005-08-16 5:44 ` Arjan van de Ven
2005-08-16 5:49 ` Arjan van de Ven
[not found] ` <20050817.110503.97359275.taka@valinux.co.jp>
2005-08-17 5:10 ` Hiro Yoshioka
2005-08-17 14:30 ` Akira Tsukamoto
2005-08-17 15:27 ` Akira Tsukamoto
2005-08-18 17:53 ` Lee Revell
2005-08-18 2:37 ` Akira Tsukamoto
-- strict thread matches above, loose matches on Subject: below --
2005-08-14 21:24 Ian Kumlien
2005-08-15 7:21 ` Arjan van de Ven
2005-08-15 14:49 ` Ian Kumlien
2005-08-15 12:15 linux
2005-08-15 12:25 ` Arjan van de Ven
[not found] <20050815121555.29159.qmail@science.horizon.com.suse.lists.linux.kernel>
[not found] ` <1124108702.3228.33.camel@laptopd505.fenrus.org.suse.lists.linux.kernel>
2005-08-15 15:02 ` Andi Kleen
2005-08-15 15:09 ` Arjan van de Ven
2005-08-15 15:13 ` Andi Kleen
[not found] <20050816.131729.15816429.taka@valinux.co.jp.suse.lists.linux.kernel>
[not found] ` <20050816.135425.719901536.hyoshiok@miraclelinux.com.suse.lists.linux.kernel>
[not found] ` <1124171015.3215.0.camel@laptopd505.fenrus.org.suse.lists.linux.kernel>
[not found] ` <20050816.191617.1025215458.hyoshiok@miraclelinux.com.suse.lists.linux.kernel>
[not found] ` <1124187950.3215.31.camel@laptopd505.fenrus.org.suse.lists.linux.kernel>
2005-08-16 13:15 ` Andi Kleen
2005-08-18 11:06 ` Hiro Yoshioka
2005-08-18 11:11 ` Hiro Yoshioka
2005-08-18 23:29 ` Hiro Yoshioka
2005-08-22 1:24 ` Hiro Yoshioka
2005-08-22 13:07 ` Andi Kleen
2005-08-22 2:43 ` Hiro Yoshioka
2005-08-22 23:12 ` Hiro Yoshioka
2005-08-24 14:11 ` Hiro Yoshioka
2005-08-24 14:21 ` Arjan van de Ven
2005-08-24 16:22 ` Hirokazu Takahashi
2005-08-25 4:53 ` Hiro Yoshioka
2005-08-16 18:09 Chuck Ebbert
2005-08-16 23:21 ` Hiro Yoshioka
2005-08-17 4:50 ` Hiro Yoshioka
2005-08-17 15:19 Chuck Ebbert
2005-08-18 9:45 ` Hiro Yoshioka
[not found] <20050818.201138.607962419.hyoshiok@miraclelinux.com.suse.lists.linux.kernel>
[not found] ` <98df96d30508181629d85edb5@mail.gmail.com.suse.lists.linux.kernel>
[not found] ` <20050823.081246.846946371.hyoshiok@miraclelinux.com.suse.lists.linux.kernel>
[not found] ` <20050824.231156.278740508.hyoshiok@miraclelinux.com.suse.lists.linux.kernel>
2005-08-24 16:18 ` Andi Kleen
2005-08-25 4:54 ` Hiro Yoshioka
2005-09-01 9:07 ` Hiro Yoshioka
2005-09-01 9:36 ` Andi Kleen
2005-09-02 1:43 ` Hiro Yoshioka
2005-09-02 2:06 ` Andi Kleen
2005-09-02 2:08 ` Andrew Morton
2005-09-02 2:17 ` Andi Kleen
2005-09-02 2:28 ` Andrew Morton
2005-09-02 3:41 ` Hiro Yoshioka
2005-09-02 4:29 ` Andrew Morton
2005-09-02 4:37 ` Hiro Yoshioka
2005-09-03 11:59 ` Hiro Yoshioka
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=98df96d305081402164ce52f8@mail.gmail.com \
--to=lkml.hyoshiok@gmail.com \
--cc=hyoshiok@miraclelinux.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox