Date: Sun, 28 Jun 2015 14:44:18 +0000 From: "emaste (Ed Maste)" <phabric-noreply@FreeBSD.org> To: freebsd-toolchain@freebsd.org Subject: [Differential] [Request, 20 lines] D2933: Significantly speed up ar(1) on UFS file systems Message-ID: <differential-rev-PHID-DREV-hkid5hylfsbts6yuvnph-req@FreeBSD.org>
index | next in thread | raw e-mail
[-- Attachment #1 --]
emaste created this revision.
emaste added a reviewer: kib.
emaste added subscribers: davide, dim, freebsd-toolchain-list, kib.
REVISION SUMMARY
Fault in the buffer prior to writing as a workaround for poor performance due to interaction with kernel fs deadlock avoidance code. See the comment prior to vn_io_fault_doio() in vfs_vnops.c for details of the issue.
Thanks @kib for diagnosing, providing an explanation of the issue and workaround.
TEST PLAN
```
% truncate -s 16M obj.o
% ar r out.a obj.o
```
Total time with stock and patched ar(1):
```
x ar.r284891
+ ar.patched
+----------------------------------------------------------------------+
|+ |
|+ x|
|+ xx|
|A |A|
+----------------------------------------------------------------------+
N Min Max Median Avg Stddev
x 3 1.307 1.321 1.315 1.3143333 0.0070237692
+ 3 0.02 0.023 0.022 0.021666667 0.0015275252
Difference at 95.0% confidence
-1.29267 +/- 0.0115203
-98.3515% +/- 0.876513%
(Student's t, pooled s = 0.00508265)
```
REVISION DETAIL
https://reviews.freebsd.org/D2933
AFFECTED FILES
usr.bin/ar/write.c
CHANGE DETAILS
diff --git a/usr.bin/ar/write.c b/usr.bin/ar/write.c
--- a/usr.bin/ar/write.c
+++ b/usr.bin/ar/write.c
@@ -41,6 +41,7 @@
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
+#include <unistd.h>
#include "ar.h"
@@ -61,6 +62,7 @@
static void free_obj(struct bsdar *bsdar, struct ar_obj *obj);
static void insert_obj(struct bsdar *bsdar, struct ar_obj *obj,
struct ar_obj *pos);
+static void prefault_buffer(const char *buf, size_t s);
static void read_objs(struct bsdar *bsdar, const char *archive,
int checkargv);
static void write_archive(struct bsdar *bsdar, char mode);
@@ -551,11 +553,29 @@
}
/*
+ * Fault in the buffer prior to writing as a workaround for poor performance
+ * due to interaction with kernel fs deadlock avoidance code. See the comment
+ * prior to vn_io_fault_doio() in vfs_vnops.c for details of the issue.
+ */
+static void
+prefault_buffer(const char *buf, size_t s)
+{
+ volatile const char *p;
+ size_t page_size;
+
+ page_size = sysconf(_SC_PAGESIZE);
+ for (p = buf; p < buf + s;
+ p += page_size - ((uintptr_t)p & page_size - 1))
+ *p;
+}
+
+/*
* Wrapper for archive_write_data().
*/
static void
write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s)
{
+ prefault_buffer(buf, s);
if (archive_write_data(a, buf, s) != (ssize_t)s)
bsdar_errc(bsdar, EX_SOFTWARE, 0, "%s",
archive_error_string(a));
EMAIL PREFERENCES
https://reviews.freebsd.org/settings/panel/emailpreferences/
To: emaste, kib
Cc: kib, freebsd-toolchain-list, dim, davide
[-- Attachment #2 --]
diff --git a/usr.bin/ar/write.c b/usr.bin/ar/write.c
--- a/usr.bin/ar/write.c
+++ b/usr.bin/ar/write.c
@@ -41,6 +41,7 @@
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
+#include <unistd.h>
#include "ar.h"
@@ -61,6 +62,7 @@
static void free_obj(struct bsdar *bsdar, struct ar_obj *obj);
static void insert_obj(struct bsdar *bsdar, struct ar_obj *obj,
struct ar_obj *pos);
+static void prefault_buffer(const char *buf, size_t s);
static void read_objs(struct bsdar *bsdar, const char *archive,
int checkargv);
static void write_archive(struct bsdar *bsdar, char mode);
@@ -551,11 +553,29 @@
}
/*
+ * Fault in the buffer prior to writing as a workaround for poor performance
+ * due to interaction with kernel fs deadlock avoidance code. See the comment
+ * prior to vn_io_fault_doio() in vfs_vnops.c for details of the issue.
+ */
+static void
+prefault_buffer(const char *buf, size_t s)
+{
+ volatile const char *p;
+ size_t page_size;
+
+ page_size = sysconf(_SC_PAGESIZE);
+ for (p = buf; p < buf + s;
+ p += page_size - ((uintptr_t)p & page_size - 1))
+ *p;
+}
+
+/*
* Wrapper for archive_write_data().
*/
static void
write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s)
{
+ prefault_buffer(buf, s);
if (archive_write_data(a, buf, s) != (ssize_t)s)
bsdar_errc(bsdar, EX_SOFTWARE, 0, "%s",
archive_error_string(a));
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?differential-rev-PHID-DREV-hkid5hylfsbts6yuvnph-req>
