bebbo / libnix

libnix (v4): a C link library for AmigaOS/m68k
14 stars 9 forks source link

fgetc() is VERY slow #66

Closed githubaf closed 1 year ago

githubaf commented 1 year ago

In WCS I stumbled over fgetc() recently. First I thought WCS had crashed but it is just extremely slow when using fgetc().

The problem happens when an ASCII elevations file should be converted to another format. The ASCII file is read char by char until a number string is complete, then the string is converted using atoi()

I extracted a little example. When compiled with SAS/C it needs about a second to complete on WinUAE (JIT). When compiled with gcc and noixemul (as of 8.March23) it needs about 100(!) seconds to complete on the same WinUAE. When I replace fopen(), fgetc() and fclose() by Open(), FGetC() and Close it becomes as fast as the SAS/C version - but I would not really like to change the original code when it is not absolutely necessary.

Is there anything you could do about that? Please find the source and the ASCII data file in attached archive.

/*

sc fgetc_test.c OPTIMIZE LINK

m68k-amigaos-gcc -O2 -Wall -noixemul -c -o fgetc_test_68k.o fgetc_test.c m68k-amigaos-gcc -noixemul -o fgetc_test_68k fgetc_test_68k.o

gcc -O2 -Wall -o fgetc_test_linux fgetc_test.c

*/

include

include

include

ifdef AMIGA

include <exec/types.h>

else

define ULONG int

endif

define INPUT_ROWS 258

define INPUT_COLS 258

//#define ADOS_FUNCTIONS // use FGetc() instead of fgetc -> HUGE speed boos in GCC version

ifdef ADOS_FUNCTIONS

include <proto/dos.h>

define fgetc FGetC

define fopen Open

define fclose Close

endif

int main(void) { long InputValues, ct; char InputChar, InValue[64]; short error=0,j; char * filename="AF_ALPS_Float.txt"; // ASCII data ULONG TotalSum=0; time_t StartTime=time(NULL);

ifdef ADOS_FUNCTIONS

BPTR fAscii; if ((fAscii = fopen(filename, MODE_OLDFILE)) == 0)

else

FILE* fAscii; if ((fAscii = fopen(filename, "r")) == NULL)

endif

{
error = 2;
printf("Could not open file %s\n",filename);
goto Cleanup;
} /* if open fail */

InputValues = INPUT_ROWS INPUT_COLS; for (ct=0; ct<InputValues; ct++) { ReadMore: if ((InputChar = fgetc(fAscii)) == EOF) { error = 3; break; } if (InputChar < 45 || InputChar > 57) // AF: < '-' || > '9' i.e. not in "-0123456789" goto ReadMore; InValue[0] = InputChar; j = 0; while (j < 63 && InValue[j] > 44 && InValue[j] < 58 && InValue[j] != EOF) //AF: > ',' && < ':' i.e. in "-0123456789" { j ++; InValue[j] = fgetc(fAscii); } /while */ if (j >= 63) // max 63 characters + final \0 { error = 3; break; } InValue[j] = '\0';

if((ct%1000)==0){ printf("ct=%ld, InValue=%s    \r",ct,InValue); }

TotalSum += (ULONG)(atoi(InValue));

} /* for i=0... */

printf("\n");

printf("Sum of all values is %d\n",TotalSum); if(TotalSum==60286033) { printf("OK\n"); } else { error=3; printf("Wrong sum!\n"); }

printf("Duration: %u seconds\n",(ULONG)(time(NULL) - StartTime));

Cleanup: fclose(fAscii);

return error; }

fgetc_test.zip

bebbo commented 1 year ago

I rather fixed vamos^^

githubaf commented 1 year ago

Why vamos? It is so slow on WinUAE / Amiga when compiled with gcc.

bebbo commented 1 year ago

vamos - a python program - used read() on stdin which waits until the buffersize is full. That's the reasone I limited reading to 1. Now with vamos using read1() - partial reading what's available - that bogus change is no longer necessary