sch@oce-rd1.oce.nl (Jakob Schripsema) (09/16/87)
When using MicroEmacs (3.8i) with PC-NFS I ran into a performance problem : Writing a file to the local hard-disk took 8 secs, writting the same file to the virtual disk took 80 secs. The problem seems to be in the MicroSoft library (I'm using MSC 3.0). The stdio code does \n to \r\n conversion. When encountering a \n the filebuffer seems to get flushed (1 write syscall) and a \r\n is added (another write syscall). After that buffering continues. This creates a lot of write calls with relatively short byte counts. This seems to upset PC-NFS. The cure is simple: open the file in binary mode and do the \n to \r\n yourself. Changes are in the routines 'ffwopen' and 'ffputline' in the file 'fileio.c'. The changed version is attached to this message. JaKob Schripsema (sch@oce.nl) Oce-Nederland B.V. The Netherlands ====================================================== This note does not necessarily represent the position of Oce-Nederland B.V. Therefore no liability or responsibility for whatever will be accepted. ====================================================== ----------- cut here ----- /* * The routines in this file read and write ASCII files from the disk. All of * the knowledge about files are here. A better message writing scheme should * be used. */ #include <stdio.h> #include "estruct.h" #include "edef.h" FILE *ffp; /* File pointer, all functions. */ /* * Open a file for reading. */ ffropen(fn) char *fn; { if ((ffp=fopen(fn, "r")) == NULL) return (FIOFNF); return (FIOSUC); } /* * Open a file for writing. Return TRUE if all is well, and FALSE on error * (cannot create). */ ffwopen(fn) char *fn; { #if VMS register int fd; if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0 || (ffp=fdopen(fd, "w")) == NULL) { #else #if MSDOS if ((ffp=fopen(fn, "wb")) == NULL) { #else if ((ffp=fopen(fn, "w")) == NULL) { #endif #endif mlwrite("Cannot open file for writing"); return (FIOERR); } return (FIOSUC); } /* * Close a file. Should look at the status in all systems. */ ffclose() { #if MSDOS & CTRLZ fputc(26, ffp); /* add a ^Z at the end of the file */ #endif #if V7 | USG | BSD | (MSDOS & (LATTICE | MSC)) if (fclose(ffp) != FALSE) { mlwrite("Error closing file"); return(FIOERR); } return(FIOSUC); #else fclose(ffp); return (FIOSUC); #endif } /* * Write a line to the already opened file. The "buf" points to the buffer, * and the "nbuf" is its length, less the free newline. Return the status. * Check only at the newline. */ ffputline(buf, nbuf) char buf[]; { register int i; #if CRYPT char c; /* character to translate */ if (cryptflag) { for (i = 0; i < nbuf; ++i) { c = buf[i] & 0xff; crypt(&c, 1); fputc(c, ffp); } } else for (i = 0; i < nbuf; ++i) fputc(buf[i]&0xFF, ffp); #else for (i = 0; i < nbuf; ++i) fputc(buf[i]&0xFF, ffp); #endif #if ST520 | MSDOS fputc('\r', ffp); #endif fputc('\n', ffp); if (ferror(ffp)) { mlwrite("Write I/O error"); return (FIOERR); } return (FIOSUC); } /* * Read a line from a file, and store the bytes in the supplied buffer. The * "nbuf" is the length of the buffer. Complain about long lines and lines * at the end of the file that don't have a newline present. Check for I/O * errors too. Return status. */ ffgetline(buf, nbuf) register char buf[]; { register int c; register int i; i = 0; while ((c = fgetc(ffp)) != EOF && c != '\n') { if (i >= nbuf-2) { buf[nbuf - 2] = c; /* store last char read */ buf[nbuf - 1] = 0; /* and terminate it */ mlwrite("File has long line"); #if CRYPT if (cryptflag) crypt(buf, strlen(buf)); #endif return (FIOLNG); } buf[i++] = c; } #if ST520 if(buf[i-1] == '\r') i--; #endif if (c == EOF) { if (ferror(ffp)) { mlwrite("File read error"); return (FIOERR); } if (i != 0) { buf[i] = 0; return(FIOFUN); } return (FIOEOF); } buf[i] = 0; #if CRYPT if (cryptflag) crypt(buf, strlen(buf)); #endif return (FIOSUC); } #if AZTEC & MSDOS #undef fgetc /* a1getc: Get an ascii char from the file input stream but DO NOT strip the high bit */ int a1getc(fp) FILE *fp; { int c; /* translated character */ c = getc(fp); /* get the character */ /* if its a <LF> char, throw it out */ while (c == 10) c = getc(fp); /* if its a <RETURN> char, change it to a LF */ if (c == '\r') c = '\n'; /* if its a ^Z, its an EOF */ if (c == 26) c = EOF; return(c); } #endif