speed up ar(1) on UFS file systems
Fault in the buffer prior to writing to workaround poor performance due to interaction with kernel fs deadlock avoidance code. See the comment prior to vn_io_fault_doio() in sys/kern/vfs_vnops.c for details of the issue. On my stable/10 desktop with a 16MB obj.o and "ar r out.a obj.o" I see the following run times (seconds): 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.020 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) Thanks to kib for diagnosing and explaining the issue and suggesting the workaround. Reviewed by: eadler, kib MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D2933
This commit is contained in:
parent
521987c3e5
commit
01715d8cd1
@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ar.h"
|
||||
|
||||
@ -61,6 +62,7 @@ static void create_symtab_entry(struct bsdar *bsdar, void *maddr,
|
||||
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);
|
||||
@ -550,12 +552,36 @@ write_cleanup(struct bsdar *bsdar)
|
||||
bsdar->s_sn = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* above vn_io_fault_doio() in sys/kern/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;
|
||||
|
||||
if (s == 0)
|
||||
return;
|
||||
page_size = sysconf(_SC_PAGESIZE);
|
||||
for (p = buf; p < buf + s; p += page_size)
|
||||
*p;
|
||||
/*
|
||||
* Ensure we touch the last page as well, in case the buffer is not
|
||||
* page-aligned.
|
||||
*/
|
||||
*(volatile const char *)(buf + s - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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));
|
||||
|
Loading…
Reference in New Issue
Block a user