From a99e649a6b49ae072e21a5355ab8fa27469e14e3 Mon Sep 17 00:00:00 2001 From: Zeex Date: Sun, 22 Oct 2017 12:23:33 +0600 Subject: [PATCH] Group sequences of repeating literals into one write Add a new "dumpn" pseudo-opcode that dumps N copies of the same value to the stage buffer. It's basically the same as "dump" but much faster when dumping the same value a lot of times, for example, when writing initial values for large arrays. On my Linux system the time it took to dump a 100000000 cell array went down from 20 to 8 seconds in Release configuration, i.e. 2.5 times faster! I haven't profiled further yet (Visual Studio 2017 profiler is broken, gprof won't output anything (I'm probably doing it wrong), I might try valgrind later). --- source/compiler/libpawnc.c | 6 +++- source/compiler/sc.h | 1 + source/compiler/sc1.c | 66 ++++++++++++++++++++++---------------- source/compiler/sc4.c | 9 ++++++ source/compiler/sc6.c | 16 ++++++++- 5 files changed, 68 insertions(+), 30 deletions(-) diff --git a/source/compiler/libpawnc.c b/source/compiler/libpawnc.c index 4a94765..78be777 100644 --- a/source/compiler/libpawnc.c +++ b/source/compiler/libpawnc.c @@ -327,7 +327,11 @@ char *pc_readasm(void *handle, char *string, int maxchars) */ void *pc_openbin(char *filename) { - return fopen(filename,"wb"); + FILE *fbin; + + fbin=fopen(filename,"wb"); + setvbuf(fbin,NULL,_IOFBF,1UL<<20); + return fbin; } void pc_closebin(void *handle,int deletefile) diff --git a/source/compiler/sc.h b/source/compiler/sc.h index a26b9d2..9639725 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -639,6 +639,7 @@ SC_FUNC void ffabort(int reason); SC_FUNC void ffbounds(cell size); SC_FUNC void jumplabel(int number); SC_FUNC void defstorage(void); +SC_FUNC void defcompactstorage(void); SC_FUNC void getfrm(void); SC_FUNC void modstk(int delta); SC_FUNC void setstk(cell value); diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index cff8561..5822946 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -414,7 +414,11 @@ char *pc_readasm(void *handle, char *string, int maxchars) */ void *pc_openbin(char *filename) { - return fopen(filename,"wb"); + FILE *fbin; + + fbin=fopen(filename,"wb"); + setvbuf(fbin,NULL,_IOFBF,1UL<<20); + return fbin; } void pc_closebin(void *handle,int deletefile) @@ -1716,29 +1720,42 @@ static void parse(void) */ static void dumplits(void) { - int j,k; + int i,j; + static const int row_len=16; if (sc_status==statSKIP) return; - k=0; - while (k=row_len-1) { + int count=j-i; + defcompactstorage(); + outval(litq[i],FALSE); stgwrite(" "); - k++; - j--; - if (j==0 || k>=litidx) - stgwrite("\n"); /* force a newline after 10 dumps */ - /* Note: stgwrite() buffers a line until it is complete. It recognizes - * the end of line as a sequence of "\n\0", so something like "\n\t" - * so should not be passed to stgwrite(). - */ - } /* while */ + outval(count,TRUE); + i+=count; + } else { + defstorage(); + j=row_len; /* 16 values per line */ + while (j && i=litidx) + stgwrite("\n"); /* force a newline after 10 dumps */ + /* Note: stgwrite() buffers a line until it is complete. It recognizes + * the end of line as a sequence of "\n\0", so something like "\n\t" + * so should not be passed to stgwrite(). + */ + } /* while */ + } /* if */ } /* while */ } @@ -1748,20 +1765,13 @@ static void dumplits(void) */ static void dumpzero(int count) { - int i; - if (sc_status==statSKIP || count<=0) return; assert(curseg==2); - defstorage(); - i=0; - while (count-- > 0) { - outval(0, FALSE); - i=(i+1) % 16; - stgwrite((i==0 || count==0) ? "\n" : " "); - if (i==0 && count>0) - defstorage(); - } /* while */ + defcompactstorage(); + outval(0, FALSE); + stgwrite(" "); + outval(count, TRUE); } static void aligndata(int numbytes) diff --git a/source/compiler/sc4.c b/source/compiler/sc4.c index 4124883..c2ea105 100644 --- a/source/compiler/sc4.c +++ b/source/compiler/sc4.c @@ -832,6 +832,15 @@ SC_FUNC void defstorage(void) stgwrite("dump "); } +/* + * Same as defstorage() but for repeating values. + */ + +SC_FUNC void defcompactstorage() +{ + stgwrite("dumpn "); +} + /* * Copies frame address to primary register */ diff --git a/source/compiler/sc6.c b/source/compiler/sc6.c index 4f89a63..9007477 100644 --- a/source/compiler/sc6.c +++ b/source/compiler/sc6.c @@ -382,7 +382,7 @@ static cell OPHANDLER_CALL parm5(FILE *fbin,char *params,cell opcode) static cell OPHANDLER_CALL do_dump(FILE *fbin,char *params,cell opcode) { ucell p; - int num = 0; + int num=0; while (*params!='\0') { p=getparam(params,¶ms); @@ -395,6 +395,19 @@ static cell OPHANDLER_CALL do_dump(FILE *fbin,char *params,cell opcode) return num*sizeof(cell); } +static cell OPHANDLER_CALL do_dumpn(FILE *fbin,char *params,cell opcode) +{ + ucell value,num,i; + + value=getparam(params,¶ms); + num=getparam(params,NULL); + if (fbin!=NULL) { + for (i=0; i