<div dir="ltr"><div style>On Wed, May 15, 2013 at 5:31 PM, Bill Wendling <span dir="ltr"><<a href="mailto:isanbard@gmail.com" target="_blank">isanbard@gmail.com</a>></span> wrote:<br></div><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: void<br>
Date: Wed May 15 16:31:22 2013<br>
New Revision: 181924<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=181924&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=181924&view=rev</a><br>
Log:<br>
Try to improve performance by using a read/write buffer instead of I/O.<br>
<br>
The calls to fwrite/fread can be very expensive. GCC avoids this by using a<br>
buffer to read and write from the file, thus limiting the number of fwrite/fread<br>
calls.<br>
<br>
<rdar://problem/13466086><br>
<br>
Modified:<br>
compiler-rt/trunk/SDKs/darwin/usr/include/stdio.h<br>
compiler-rt/trunk/SDKs/darwin/usr/include/string.h<br>
compiler-rt/trunk/SDKs/linux/usr/include/stdio.h<br>
compiler-rt/trunk/SDKs/linux/usr/include/string.h<br>
compiler-rt/trunk/lib/profile/GCDAProfiling.c<br>
<br>
Modified: compiler-rt/trunk/SDKs/darwin/usr/include/stdio.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/SDKs/darwin/usr/include/stdio.h?rev=181924&r1=181923&r2=181924&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/SDKs/darwin/usr/include/stdio.h?rev=181924&r1=181923&r2=181924&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/SDKs/darwin/usr/include/stdio.h (original)<br>
+++ compiler-rt/trunk/SDKs/darwin/usr/include/stdio.h Wed May 15 16:31:22 2013<br>
@@ -74,6 +74,7 @@ size_t fwrite(const void * __restrict, s<br>
size_t fread(void * __restrict, size_t, size_t, FILE * __restrict);<br>
long ftell(FILE *);<br>
int fseek(FILE *, long, int);<br>
+void setbuf(FILE * __restrict, char * __restrict);<br>
<br>
int snprintf(char * __restrict, size_t, const char * __restrict, ...);<br>
<br>
<br>
Modified: compiler-rt/trunk/SDKs/darwin/usr/include/string.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/SDKs/darwin/usr/include/string.h?rev=181924&r1=181923&r2=181924&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/SDKs/darwin/usr/include/string.h?rev=181924&r1=181923&r2=181924&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/SDKs/darwin/usr/include/string.h (original)<br>
+++ compiler-rt/trunk/SDKs/darwin/usr/include/string.h Wed May 15 16:31:22 2013<br>
@@ -21,6 +21,7 @@ typedef __SIZE_TYPE__ size_t;<br>
<br>
int memcmp(const void *, const void *, size_t);<br>
void *memcpy(void *, const void *, size_t);<br>
+void *memset(void *, int, size_t);<br>
char *strcat(char *, const char *);<br>
char *strcpy(char *, const char *);<br>
char *strdup(const char *);<br>
<br>
Modified: compiler-rt/trunk/SDKs/linux/usr/include/stdio.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/SDKs/linux/usr/include/stdio.h?rev=181924&r1=181923&r2=181924&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/SDKs/linux/usr/include/stdio.h?rev=181924&r1=181923&r2=181924&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/SDKs/linux/usr/include/stdio.h (original)<br>
+++ compiler-rt/trunk/SDKs/linux/usr/include/stdio.h Wed May 15 16:31:22 2013<br>
@@ -38,5 +38,6 @@ extern size_t fwrite(const void * restri<br>
extern size_t fread(void * restrict, size_t, size_t, FILE * restrict);<br>
extern long ftell(FILE *);<br>
extern int fseek(FILE *, long, int);<br>
+extern void setbuf(FILE * restrict, char * restrict);<br>
<br>
#endif /* __STDIO_H__ */<br>
<br>
Modified: compiler-rt/trunk/SDKs/linux/usr/include/string.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/SDKs/linux/usr/include/string.h?rev=181924&r1=181923&r2=181924&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/SDKs/linux/usr/include/string.h?rev=181924&r1=181923&r2=181924&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/SDKs/linux/usr/include/string.h (original)<br>
+++ compiler-rt/trunk/SDKs/linux/usr/include/string.h Wed May 15 16:31:22 2013<br>
@@ -21,6 +21,7 @@ typedef __SIZE_TYPE__ size_t;<br>
<br>
int memcmp(const void *, const void *, size_t);<br>
void *memcpy(void *, const void *, size_t);<br>
+void *memset(void *, int, size_t);<br>
char *strcat(char *, const char *);<br>
char *strcpy(char *, const char *);<br>
char *strdup(const char *);<br>
<br>
Modified: compiler-rt/trunk/lib/profile/GCDAProfiling.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/GCDAProfiling.c?rev=181924&r1=181923&r2=181924&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/GCDAProfiling.c?rev=181924&r1=181923&r2=181924&view=diff</a><br>
==============================================================================<br>
--- compiler-rt/trunk/lib/profile/GCDAProfiling.c (original)<br>
+++ compiler-rt/trunk/lib/profile/GCDAProfiling.c Wed May 15 16:31:22 2013<br>
@@ -48,6 +48,15 @@ typedef unsigned int uint64_t;<br>
static FILE *output_file = NULL;<br>
<br>
/*<br>
+ * Buffer that we write things into.<br>
+ */<br>
+#define WRITE_BUFFER_SIZE (1 << 12)<br>
+static char write_buffer[WRITE_BUFFER_SIZE];<br>
+static int64_t cur_file_pos = 0;<br>
+static uint32_t cur_offset = 0;<br>
+static int new_file = 0;<br>
+<br>
+/*<br>
* A list of functions to write out the data.<br>
*/<br>
typedef void (*writeout_fn)();<br>
@@ -57,8 +66,8 @@ struct writeout_fn_node {<br>
struct writeout_fn_node *next;<br>
};<br>
<br>
-struct writeout_fn_node *writeout_fn_head = NULL;<br>
-struct writeout_fn_node *writeout_fn_tail = NULL;<br>
+static struct writeout_fn_node *writeout_fn_head = NULL;<br>
+static struct writeout_fn_node *writeout_fn_tail = NULL;<br>
<br>
/*<br>
* A list of flush functions that our __gcov_flush() function should call.<br>
@@ -70,18 +79,41 @@ struct flush_fn_node {<br>
struct flush_fn_node *next;<br>
};<br>
<br>
-struct flush_fn_node *flush_fn_head = NULL;<br>
-struct flush_fn_node *flush_fn_tail = NULL;<br>
+static struct flush_fn_node *flush_fn_head = NULL;<br>
+static struct flush_fn_node *flush_fn_tail = NULL;<br>
+<br>
+static void flush_buffer() {<br>
+ /* Flush the buffer to file. */<br>
+ fwrite(write_buffer, cur_offset, 1, output_file);<br>
+<br>
+ if (new_file) {<br>
+ cur_offset = 0;<br>
+ return;<br>
+ }<br>
+<br>
+ /* Read in more of the file. */<br>
+ fread(write_buffer,1, WRITE_BUFFER_SIZE, output_file);<br>
+ fseek(output_file, cur_file_pos, SEEK_SET);<br>
<br>
-static void write_int32(uint32_t i) {<br>
- fwrite(&i, 4, 1, output_file);<br>
+ cur_offset = 0;<br>
}<br>
<br>
-static uint64_t write_from_buffer(uint64_t *buffer, size_t size) {<br>
- if (fwrite(buffer, 8, size, output_file) != size)<br>
- return (uint64_t)-1;<br>
+static void write_bytes(const char *s, size_t len) {<br>
+ if (cur_offset + len > WRITE_BUFFER_SIZE)<br>
+ flush_buffer();<br></blockquote><div><br></div><div style>Can len be > WRITE_BUFFER_SIZE? </div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ cur_file_pos += len;<br>
+<br>
+ for (; len > 0; --len)<br>
+ write_buffer[cur_offset++] = *s++;<br>
+}<br>
<br>
- return 0;<br>
+static void write_32bit_value(uint32_t i) {<br>
+ write_bytes((char*)&i, 4);<br>
+}<br>
+<br>
+static void write_64bit_value(uint64_t i) {<br>
+ write_bytes((char*)&i, 8);<br>
}<br>
<br>
static uint32_t length_of_string(const char *s) {<br>
@@ -90,25 +122,39 @@ static uint32_t length_of_string(const c<br>
<br>
static void write_string(const char *s) {<br>
uint32_t len = length_of_string(s);<br>
- write_int32(len);<br>
- fwrite(s, strlen(s), 1, output_file);<br>
- fwrite("\0\0\0\0", 4 - (strlen(s) % 4), 1, output_file);<br>
+ write_32bit_value(len);<br>
+ write_bytes(s, strlen(s));<br>
+ write_bytes("\0\0\0\0", 4 - (strlen(s) % 4));<br>
}<br>
<br>
-static uint32_t read_int32() {<br>
- uint32_t tmp;<br>
+static uint32_t read_32bit_value() {<br>
+ uint32_t val;<br>
+<br>
+ if (cur_offset + 4 > WRITE_BUFFER_SIZE)<br>
+ flush_buffer();<br>
<br>
- if (fread(&tmp, 1, 4, output_file) != 4)<br>
+ if (new_file)<br>
return (uint32_t)-1;<br>
<br>
- return tmp;<br>
+ val = *(uint32_t*)&write_buffer[cur_offset];<br>
+ cur_file_pos += 4;<br>
+ cur_offset += 4;<br>
+ return val;<br>
}<br>
<br>
-static uint64_t read_into_buffer(uint64_t *buffer, size_t size) {<br>
- if (fread(buffer, 8, size, output_file) != size)<br>
- return (uint64_t)-1;<br>
+static uint64_t read_64bit_value() {<br>
+ uint64_t val;<br>
<br>
- return 0;<br>
+ if (cur_offset + 8 > WRITE_BUFFER_SIZE)<br>
+ flush_buffer();<br>
+<br>
+ if (new_file)<br>
+ return (uint32_t)-1;<br>
+<br>
+ val = *(uint64_t*)&write_buffer[cur_offset];<br>
+ cur_file_pos += 8;<br>
+ cur_offset += 8;<br>
+ return val;<br>
}<br>
<br>
static char *mangle_filename(const char *orig_filename) {<br>
@@ -118,13 +164,13 @@ static char *mangle_filename(const char<br>
int level = 0;<br>
const char *fname = orig_filename, *ptr = NULL;<br>
const char *prefix = getenv("GCOV_PREFIX");<br>
- const char *tmp = getenv("GCOV_PREFIX_STRIP");<br>
+ const char *prefix_strip_str = getenv("GCOV_PREFIX_STRIP");<br>
<br>
if (!prefix)<br>
return strdup(orig_filename);<br>
<br>
- if (tmp) {<br>
- prefix_strip = atoi(tmp);<br>
+ if (prefix_strip_str) {<br>
+ prefix_strip = atoi(prefix_strip_str);<br>
<br>
/* Negative GCOV_PREFIX_STRIP values are ignored */<br>
if (prefix_strip < 0)<br>
@@ -180,6 +226,7 @@ void llvm_gcda_start_file(const char *or<br>
<br>
if (!output_file) {<br>
/* Try opening the file, creating it if necessary. */<br>
+ new_file = 1;<br>
output_file = fopen(filename, "w+b");<br>
if (!output_file) {<br>
/* Try creating the directories first then opening the file. */<br>
@@ -194,10 +241,20 @@ void llvm_gcda_start_file(const char *or<br>
}<br>
}<br>
<br>
+ setbuf(output_file, 0);<br>
+<br>
+ /* Initialize the write buffer. */<br>
+ memset(write_buffer, 0, WRITE_BUFFER_SIZE);<br>
+ fread(write_buffer, 1, WRITE_BUFFER_SIZE, output_file);<br>
+ fseek(output_file, 0L, SEEK_SET);<br>
+ cur_file_pos = 0;<br>
+ cur_offset = 0;<br>
+<br>
/* gcda file, version, stamp LLVM. */<br>
- fwrite("adcg", 4, 1, output_file);<br>
- fwrite(version, 4, 1, output_file);<br>
- fwrite("MVLL", 4, 1, output_file);<br>
+ write_bytes("adcg", 4);<br>
+ write_bytes(version, 4);<br>
+ write_bytes("MVLL", 4);<br>
+<br>
free(filename);<br>
<br>
#ifdef DEBUG_GCDAPROFILING<br>
@@ -233,6 +290,7 @@ void llvm_gcda_increment_indirect_counte<br>
void llvm_gcda_emit_function(uint32_t ident, const char *function_name,<br>
uint8_t use_extra_checksum) {<br>
uint32_t len = 2;<br>
+<br>
if (use_extra_checksum)<br>
len++;<br>
#ifdef DEBUG_GCDAPROFILING<br>
@@ -242,14 +300,14 @@ void llvm_gcda_emit_function(uint32_t id<br>
if (!output_file) return;<br>
<br>
/* function tag */<br>
- fwrite("\0\0\0\1", 4, 1, output_file);<br>
+ write_bytes("\0\0\0\1", 4);<br>
if (function_name)<br>
len += 1 + length_of_string(function_name);<br>
- write_int32(len);<br>
- write_int32(ident);<br>
- write_int32(0);<br>
+ write_32bit_value(len);<br>
+ write_32bit_value(ident);<br>
+ write_32bit_value(0);<br>
if (use_extra_checksum)<br>
- write_int32(0);<br>
+ write_32bit_value(0);<br>
if (function_name)<br>
write_string(function_name);<br>
}<br>
@@ -257,13 +315,13 @@ void llvm_gcda_emit_function(uint32_t id<br>
void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) {<br>
uint32_t i;<br>
uint64_t *old_ctrs = NULL;<br>
+ int64_t save_cur_file_pos = cur_file_pos;<br>
uint32_t val = 0;<br>
- long pos = 0;<br>
<br>
if (!output_file) return;<br>
<br>
- pos = ftell(output_file);<br>
- val = read_int32();<br>
+ flush_buffer();<br>
+ val = read_32bit_value();<br>
<br>
if (val != (uint32_t)-1) {<br>
/* There are counters present in the file. Merge them. */<br>
@@ -272,33 +330,30 @@ void llvm_gcda_emit_arcs(uint32_t num_co<br>
return;<br>
}<br>
<br>
- val = read_int32();<br>
+ val = read_32bit_value();<br>
if (val == (uint32_t)-1 || val / 2 != num_counters) {<br>
fprintf(stderr, "profiling:invalid number of counters (%d)\n", val);<br>
return;<br>
}<br>
<br>
old_ctrs = malloc(sizeof(uint64_t) * num_counters);<br>
+ for (i = 0; i < num_counters; ++i)<br>
+ old_ctrs[i] = read_64bit_value();<br>
<br>
- if (read_into_buffer(old_ctrs, num_counters) == (uint64_t)-1) {<br>
- fprintf(stderr, "profiling:invalid number of counters (%d)\n",<br>
- num_counters);<br>
- return;<br>
- }<br>
- }<br>
+ /* Reset the current buffer and file position. */<br>
+ memset(write_buffer, 0, WRITE_BUFFER_SIZE);<br>
+ cur_file_pos = save_cur_file_pos;<br>
+ cur_offset = 0;<br>
<br>
- /* Reset for writing. */<br>
- fseek(output_file, pos, SEEK_SET);<br>
+ fseek(output_file, cur_file_pos, SEEK_SET);<br>
+ }<br>
<br>
/* Counter #1 (arcs) tag */<br>
- fwrite("\0\0\xa1\1", 4, 1, output_file);<br>
- write_int32(num_counters * 2);<br>
- for (i = 0; i < num_counters; ++i)<br>
+ write_bytes("\0\0\xa1\1", 4);<br>
+ write_32bit_value(num_counters * 2);<br>
+ for (i = 0; i < num_counters; ++i) {<br>
counters[i] += (old_ctrs ? old_ctrs[i] : 0);<br>
-<br>
- if (write_from_buffer(counters, num_counters) == (uint64_t)-1) {<br>
- fprintf(stderr, "profiling:cannot write to output file\n");<br>
- return;<br>
+ write_64bit_value(counters[i]);<br>
}<br>
<br>
free(old_ctrs);<br>
@@ -313,7 +368,8 @@ void llvm_gcda_emit_arcs(uint32_t num_co<br>
void llvm_gcda_end_file() {<br>
/* Write out EOF record. */<br>
if (!output_file) return;<br>
- fwrite("\0\0\0\0\0\0\0\0", 8, 1, output_file);<br>
+ write_bytes("\0\0\0\0\0\0\0\0", 8);<br>
+ flush_buffer();<br>
fclose(output_file);<br>
output_file = NULL;<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>