473,396 Members | 1,827 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

cat

Jag
I've read parts of K&R's ANSI C v2 and this is what their cat looked
like but when I compared the speed of this code to gnu cat, it seems
very slow. How do I optimize this for greater speeds? is there an
alternative algorithm?

void catfile(FILE *in, FILE *out) {
register int num_char;

/*Get characters*/
while ((num_char = getc(in)) != EOF) {
/*Print to standard output*/
putc(num_char, out);
}
}

Thanks.
Mar 6 '08 #1
22 2360
Jag <ta*******@gmail.comwrites:
I've read parts of K&R's ANSI C v2 and this is what their cat looked
like but when I compared the speed of this code to gnu cat, it seems
very slow. How do I optimize this for greater speeds? is there an
alternative algorithm?

void catfile(FILE *in, FILE *out) {
register int num_char;

/*Get characters*/
while ((num_char = getc(in)) != EOF) {
/*Print to standard output*/
putc(num_char, out);
}
}
This example was intended to be just that: an example. It gives a
clear, concise method for copying in to out.

If you look at GNU cat's source code, you'll see that it's nowhere
near as clear and concise (this is due in no small part to the fact
that it has to do a good deal more than the above example does,
including some options that require a bit of processing on the input).

POSIX systems that support the thread-safety option have to lock the
I/O streams every time you call getc() or putc(). On such systems,
getc_unlocked() and putc_unlocked() (POSIX options, not Standard C)
will usually be notably faster. Some implementations also provide
other means for using the "unlocked" versions.

Other common techniques would be to read in larger blocks at a time,
or perhaps to avoid the Standard C buffered I/O calls and use POSIX
read(), write() (it's unclear to me how much better that is than to
use setvbuf() to turn off buffering and use fwrite() and fread(),
which is a good option if you'd like to stick to Standard C).

Taking a look at the source code for GNU cat and other similar
utilities like dd, for (Unix-specific) ideas on how to improve
efficiency.

--
HTH,
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 6 '08 #2
Jag wrote:
>
I've read parts of K&R's ANSI C v2 and this is what their cat
looked like but when I compared the speed of this code to gnu
cat, it seems very slow. How do I optimize this for greater
speeds? is there an alternative algorithm?

void catfile(FILE *in, FILE *out) {
register int num_char;

/*Get characters*/
while ((num_char = getc(in)) != EOF) {
/*Print to standard output*/
putc(num_char, out);
}
}
You may find the following faster:

void catfile(FILE *in, FILE *out) {
int ch;

while (EOF != (ch = getc(in))) putc(out, ch);
}

If so, consider why.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Mar 6 '08 #3
CBFalconer wrote:
Jag wrote:
>I've read parts of K&R's ANSI C v2 and this is what their cat
looked like but when I compared the speed of this code to gnu
cat, it seems very slow. How do I optimize this for greater
speeds? is there an alternative algorithm?

void catfile(FILE *in, FILE *out) {
register int num_char;

/*Get characters*/
while ((num_char = getc(in)) != EOF) {
/*Print to standard output*/
putc(num_char, out);
}
}

You may find the following faster:

void catfile(FILE *in, FILE *out) {
int ch;

while (EOF != (ch = getc(in))) putc(out, ch);
}

If so, consider why.
I don't see why it would be faster. As far as I can
tell, the only substantive change is the removal of
`register', which is unlikely to make a difference --
and if it does make a difference, it's likely to make
the revised code slower, not faster.

(Well, there's one other "speed improvement," and it
could be a large one: Code that doesn't compile uses very
little execution time! Have another look at the putc()
call ...)

--
Eric Sosman
es*****@ieee-dot-org.invalid
Mar 6 '08 #4
Ohimigod!

I am recently given to understand that cat means something other than
one-half of the dead felines in arbitrary buckets.

I sense that you drank of the forbidden K&R chapter, forbidden, not by these
jerks but by the standard, Dan Pop, Elvis, and me.

--
Gerry Ford

"Er hat sich georgiert." Der Spiegel, 2008, sich auf Chimpy Eins komma null
beziehend.
"Eric Sosman" <es*****@ieee-dot-org.invalidwrote in message
news:k8******************************@comcast.com. ..
CBFalconer wrote:
>Jag wrote:
>>I've read parts of K&R's ANSI C v2 and this is what their cat
looked like but when I compared the speed of this code to gnu
cat, it seems very slow. How do I optimize this for greater
speeds? is there an alternative algorithm?

void catfile(FILE *in, FILE *out) {
register int num_char;

/*Get characters*/
while ((num_char = getc(in)) != EOF) {
/*Print to standard output*/
putc(num_char, out);
}
}

You may find the following faster:

void catfile(FILE *in, FILE *out) {
int ch;

while (EOF != (ch = getc(in))) putc(out, ch);
}

If so, consider why.

I don't see why it would be faster. As far as I can
tell, the only substantive change is the removal of
`register', which is unlikely to make a difference --
and if it does make a difference, it's likely to make
the revised code slower, not faster.

(Well, there's one other "speed improvement," and it
could be a large one: Code that doesn't compile uses very
little execution time! Have another look at the putc()
call ...)

--
Eric Sosman
es*****@ieee-dot-org.invalid

Mar 6 '08 #5
Richard <de***@gmail.comwrites:
And on that subject I often find
it pays dividends in the maintenance stakes to always bracket off the
body of conditions even if they are only one line e.g

,----
| while(c){
| c=do(c);
| }
`----
You state that it pays dividends, but neglect to state how/why.

I'm guessing you mean that, if you have:

while(c)
c=do(c);

And then later want to add another statement in the while's body, then
you have to go through the tedium of adding braces first.

If that's what you mean, then my answer is:
- It's not appreciably harder to add braces later than it is to put
them in in the first place.
- In a decent editor, such as emacs or vim, it's simple to define a
new macro to automatically add (or remove) braces for one-line
bodies.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 6 '08 #6
Micah Cowan said:

<snip>
I'm guessing you mean that, if you have:

while(c)
c=do(c);

And then later want to add another statement in the while's body, then
you have to go through the tedium of adding braces first.
That isn't the issue. If the compound statement has two statements, you
need the braces anyway, and it doesn't make a lot of odds whether you add
them now or later. In fact, if that *were* the only issue, deferring them
could save you (a miniscule amount of) work.
If that's what you mean, then my answer is:
- It's not appreciably harder to add braces later than it is to put
them in in the first place.
Agreed. BUT - it is appreciably harder to remember to add them later on
special occasions than to put them in every time as a matter of habit.
- In a decent editor, such as emacs or vim, it's simple to define a
new macro to automatically add (or remove) braces for one-line
bodies.
That's as maybe, but it isn't the work of adding such tools - it's the work
of remembering to use them. Unless, of course, by "automatic" you really
do mean automatic!! :-)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Mar 6 '08 #7
Richard Heathfield <rj*@see.sig.invalidwrites:
>If that's what you mean, then my answer is:
- It's not appreciably harder to add braces later than it is to put
them in in the first place.

Agreed. BUT - it is appreciably harder to remember to add them later on
special occasions than to put them in every time as a matter of habit.
Hm. I haven't found it to be so.

while (c)
c=do_it(c);
c=do_another_thing(c);

looks too broken right away for me not to notice it (though, perhaps
now that I'm doing more Python coding work these days, that may
change?).

I used to actually always put the braces in. I've fallen out of that
practice, just because I find it slightly more readable without, for
one-line bodies.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 6 '08 #8
Jag
On Mar 6, 11:08 am, Micah Cowan <mi...@hollister.bcsweb.comwrote:
Jag <talon....@gmail.comwrites:
I've read parts of K&R's ANSI C v2 and this is what their cat looked
like but when I compared the speed of this code to gnu cat, it seems
very slow. How do I optimize this for greater speeds? is there an
alternative algorithm?
void catfile(FILE *in, FILE *out) {
register int num_char;
/*Get characters*/
while ((num_char = getc(in)) != EOF) {
/*Print to standard output*/
putc(num_char, out);
}
}

This example was intended to be just that: an example. It gives a
clear, concise method for copying in to out.

If you look at GNU cat's source code, you'll see that it's nowhere
near as clear and concise (this is due in no small part to the fact
that it has to do a good deal more than the above example does,
including some options that require a bit of processing on the input).

POSIX systems that support the thread-safety option have to lock the
I/O streams every time you call getc() or putc(). On such systems,
getc_unlocked() and putc_unlocked() (POSIX options, not Standard C)
will usually be notably faster. Some implementations also provide
other means for using the "unlocked" versions.

Other common techniques would be to read in larger blocks at a time,
or perhaps to avoid the Standard C buffered I/O calls and use POSIX
read(), write() (it's unclear to me how much better that is than to
use setvbuf() to turn off buffering and use fwrite() and fread(),
which is a good option if you'd like to stick to Standard C).

Taking a look at the source code for GNU cat and other similar
utilities like dd, for (Unix-specific) ideas on how to improve
efficiency.

--
HTH,
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...http://micah.cowan.name/
Thanks!
Mar 6 '08 #9
Micah Cowan wrote:
Richard Heathfield <rj*@see.sig.invalidwrites:

>>>If that's what you mean, then my answer is:
- It's not appreciably harder to add braces later than it is to put
them in in the first place.

Agreed. BUT - it is appreciably harder to remember to add them later on
special occasions than to put them in every time as a matter of habit.


Hm. I haven't found it to be so.

while (c)
c=do_it(c);
c=do_another_thing(c);

looks too broken right away for me not to notice it (though, perhaps
now that I'm doing more Python coding work these days, that may
change?).

while (c);
c= do_it(c);

the error above is harder to find than:

while (c);{
c= do_it(c);
}

you cannot miss the ';' between ')' and '{':
it is not a natural location for it, and in fact,
for this very reason, you'll rarely find such a code.

But the first mistake is often found in the code of
my students. And when they ask why their code does not work
as expected, you may have a hard time before catching
the extra semi-colon.

Mar 6 '08 #10
>>>>"r" == regis <re***@dil.univ-mrs.frwrites:

rwhile (c); c= do_it(c);

rthe error above is harder to find than:

rwhile (c);{ c= do_it(c); }

rBut the first mistake is often found in the code of my
rstudents. And when they ask why their code does not work as
rexpected, you may have a hard time before catching the extra
rsemi-colon.

And then, after a semester where they've made this mistake a
half-dozen times, either they start recognizing the symptoms of that
mistake, they have learned to single-step through suspicious code in a
debugger, or they need to switch majors to something less
intellectually taxing.

Charlton

--
Charlton Wilbur
cw*****@chromatico.net
Mar 6 '08 #11
Jag <ta*******@gmail.comwrote:
# I've read parts of K&R's ANSI C v2 and this is what their cat looked
# like but when I compared the speed of this code to gnu cat, it seems
# very slow. How do I optimize this for greater speeds? is there an
# alternative algorithm?

The system cat exploits features of the specific system that
are not available in ANSI C. For example on unix, you can
avoid stdio altogether, and do something like
read -shared buffer -write

You can also use asynchronous I/O and multiple buffers to
have overlapping reads and writes.

But all this is system specific.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
If you plan to shoplift, let us know.
Thanks
Mar 6 '08 #12
On Mar 5, 6:06*pm, Jag <talon....@gmail.comwrote:
I've read parts of K&R's ANSI C v2 and this is what their cat looked
like but when I compared the speed of this code to gnu cat, it seems
very slow. How do I optimize this for greater speeds? is there an
alternative algorithm?

void catfile(FILE *in, FILE *out) {
* * register int num_char;

* * /*Get characters*/
* * while ((num_char = getc(in)) != EOF) {
* * * * /*Print to standard output*/
* * * * putc(num_char, out);
* * }

}
C:\tmp>dir dict.sql
Volume in drive C has no label.
Volume Serial Number is 0890-87CA

Directory of C:\tmp

03/01/2007 11:48 AM 7,127,408 dict.sql
1 File(s) 7,127,408 bytes
0 Dir(s) 5,202,309,120 bytes free

C:\tmp>cat dict.sql dict.out
standard cat took 1.984000 seconds
big buffer cat took 0.000000 seconds

C:\tmp>type cat.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void catfilebuffer(FILE * in, FILE * out)
{
register int num_char;

setvbuf(in, NULL, _IOFBF, 1024 * 16);
setvbuf(out, NULL, _IOFBF, 1024 * 16);

/* Get characters */
while ((num_char = getc(in)) != EOF) {
/* Print to standard output */
putc(num_char, out);
}
}

void catfilenobuff(FILE * in, FILE * out)
{
register int num_char;

/* Get characters */
while ((num_char = getc(in)) != EOF) {
/* Print to standard output */
putc(num_char, out);
}
}

int main(int argc, char **argv)
{
FILE *in = stdin;
FILE *out = stdout;
clock_t start,
end;
static const double cps = 1.0 / CLOCKS_PER_SEC;
if (argc 1) {
in = fopen(argv[1], "r");
if (in == NULL) {
printf("Error opening %s\n", argv[1]);
exit(EXIT_FAILURE);
}
}
if (argc 2) {
out = fopen(argv[2], "w");
if (out == NULL) {
printf("Error opening %s\n", argv[2]);
exit(EXIT_FAILURE);
}
}
start = clock();
catfilenobuff(in, out);
end = clock();
printf("standard cat took %f seconds\n", (end - start) * cps);
start = clock();
catfilebuffer(in, out);
end = clock();
printf("big buffer cat took %f seconds\n", (end - start) * cps);
fflush(NULL);
return 0;
}
Mar 6 '08 #13
On Mar 6, 12:30*pm, user923005 <dcor...@connx.comwrote:
On Mar 5, 6:06*pm, Jag <talon....@gmail.comwrote:
I've read parts of K&R's ANSI C v2 and this is what their cat looked
like but when I compared the speed of this code to gnu cat, it seems
very slow. How do I optimize this for greater speeds? is there an
alternative algorithm?
void catfile(FILE *in, FILE *out) {
* * register int num_char;
* * /*Get characters*/
* * while ((num_char = getc(in)) != EOF) {
* * * * /*Print to standard output*/
* * * * putc(num_char, out);
* * }
}

C:\tmp>dir dict.sql
*Volume in drive C has no label.
*Volume Serial Number is 0890-87CA

*Directory of C:\tmp

03/01/2007 *11:48 AM * * * * 7,127,408 dict.sql
* * * * * * * *1 File(s) * * *7,127,408 bytes
* * * * * * * *0 Dir(s) * 5,202,309,120 bytes free

C:\tmp>cat dict.sql dict.out
standard cat took 1.984000 seconds
big buffer cat took 0.000000 seconds

C:\tmp>type cat.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void * * * * * *catfilebuffer(FILE * in, FILE * out)
{
* * register int * *num_char;

* * setvbuf(in, NULL, _IOFBF, 1024 * 16);
* * setvbuf(out, NULL, _IOFBF, 1024 * 16);

* * /* Get characters */
* * while ((num_char = getc(in)) != EOF) {
* * * * /* Print to standard output */
* * * * putc(num_char, out);
* * }

}

void * * * * * *catfilenobuff(FILE * in, FILE * out)
{
* * register int * *num_char;

* * /* Get characters */
* * while ((num_char = getc(in)) != EOF) {
* * * * /* Print to standard output */
* * * * putc(num_char, out);
* * }

}

int * * * * * * main(int argc, char **argv)
{
* * FILE * * * * * *in = stdin;
* * FILE * * * * * *out = stdout;
* * clock_t * * * * start,
* * * * * * * * * * end;
* * static const double *cps = 1.0 / CLOCKS_PER_SEC;
* * if (argc 1) {
* * * * in = fopen(argv[1], "r");
* * * * if (in == NULL) {
* * * * * * printf("Error opening %s\n", argv[1]);
* * * * * * exit(EXIT_FAILURE);
* * * * }
* * }
* * if (argc 2) {
* * * * out = fopen(argv[2], "w");
* * * * if (out == NULL) {
* * * * * * printf("Error opening %s\n", argv[2]);
* * * * * * exit(EXIT_FAILURE);
* * * * }
* * }
* * start = clock();
* * catfilenobuff(in, out);
* * end = clock();
* * printf("standard cat took %f seconds\n", (end - start) * cps);
* * start = clock();
* * catfilebuffer(in, out);
* * end = clock();
* * printf("big buffer cat took %f seconds\n", (end - start) * cps);
* * fflush(NULL);
* * return 0;

}
Oops. Forgot to rewind. Let me try that again...
Mar 6 '08 #14
On Mar 6, 12:30*pm, user923005 <dcor...@connx.comwrote:
On Mar 5, 6:06*pm, Jag <talon....@gmail.comwrote:
I've read parts of K&R's ANSI C v2 and this is what their cat looked
like but when I compared the speed of this code to gnu cat, it seems
very slow. How do I optimize this for greater speeds? is there an
alternative algorithm?
void catfile(FILE *in, FILE *out) {
* * register int num_char;
* * /*Get characters*/
* * while ((num_char = getc(in)) != EOF) {
* * * * /*Print to standard output*/
* * * * putc(num_char, out);
* * }
}

C:\tmp>dir dict.sql
*Volume in drive C has no label.
*Volume Serial Number is 0890-87CA

*Directory of C:\tmp

03/01/2007 *11:48 AM * * * * 7,127,408 dict.sql
* * * * * * * *1 File(s) * * *7,127,408 bytes
* * * * * * * *0 Dir(s) * 5,202,309,120 bytes free

C:\tmp>cat dict.sql dict.out
standard cat took 1.984000 seconds
big buffer cat took 0.000000 seconds

C:\tmp>type cat.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void * * * * * *catfilebuffer(FILE * in, FILE * out)
{
* * register int * *num_char;

* * setvbuf(in, NULL, _IOFBF, 1024 * 16);
* * setvbuf(out, NULL, _IOFBF, 1024 * 16);

* * /* Get characters */
* * while ((num_char = getc(in)) != EOF) {
* * * * /* Print to standard output */
* * * * putc(num_char, out);
* * }

}

void * * * * * *catfilenobuff(FILE * in, FILE * out)
{
* * register int * *num_char;

* * /* Get characters */
* * while ((num_char = getc(in)) != EOF) {
* * * * /* Print to standard output */
* * * * putc(num_char, out);
* * }

}

int * * * * * * main(int argc, char **argv)
{
* * FILE * * * * * *in = stdin;
* * FILE * * * * * *out = stdout;
* * clock_t * * * * start,
* * * * * * * * * * end;
* * static const double *cps = 1.0 / CLOCKS_PER_SEC;
* * if (argc 1) {
* * * * in = fopen(argv[1], "r");
* * * * if (in == NULL) {
* * * * * * printf("Error opening %s\n", argv[1]);
* * * * * * exit(EXIT_FAILURE);
* * * * }
* * }
* * if (argc 2) {
* * * * out = fopen(argv[2], "w");
* * * * if (out == NULL) {
* * * * * * printf("Error opening %s\n", argv[2]);
* * * * * * exit(EXIT_FAILURE);
* * * * }
* * }
* * start = clock();
* * catfilenobuff(in, out);
* * end = clock();
* * printf("standard cat took %f seconds\n", (end - start) * cps);
* * start = clock();
* * catfilebuffer(in, out);
* * end = clock();
* * printf("big buffer cat took %f seconds\n", (end - start) * cps);
* * fflush(NULL);
* * return 0;

}- Hide quoted text -

- Show quoted text -

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void catfilebuffer(FILE * in, FILE * out)
{
register int num_char;

setvbuf(in, NULL, _IOFBF, 1024 * 16);
setvbuf(out, NULL, _IOFBF, 1024 * 16);

/* Get characters */
while ((num_char = getc(in)) != EOF) {
/* Print to standard output */
putc(num_char, out);
}
}

void catfilenobuff(FILE * in, FILE * out)
{
register int num_char;

/* Get characters */
while ((num_char = getc(in)) != EOF) {
/* Print to standard output */
putc(num_char, out);
}
}

int main(int argc, char **argv)
{
FILE *in = stdin;
FILE *out = stdout;
clock_t start,
end;
static const double cps = 1.0 / CLOCKS_PER_SEC;
if (argc 1) {
in = fopen(argv[1], "r");
if (in == NULL) {
printf("Error opening %s\n", argv[1]);
exit(EXIT_FAILURE);
}
}
if (argc 2) {
out = fopen(argv[2], "w");
if (out == NULL) {
printf("Error opening %s\n", argv[2]);
exit(EXIT_FAILURE);
}
}
start = clock();
catfilenobuff(in, out);
end = clock();
printf("standard cat took %f seconds\n", (end - start) * cps);
rewind(in);
fclose(out);
if (argc 2) {
out = fopen(argv[2], "w");
if (out == NULL) {
printf("Error opening %s\n", argv[2]);
exit(EXIT_FAILURE);
}
} else
out = stdout;
start = clock();
catfilebuffer(in, out);
end = clock();
printf("big buffer cat took %f seconds\n", (end - start) * cps);
fflush(NULL);
return 0;
}
/*
Not nearly so dramatic! ;-)
C:\tmp>cat dict.sql dict.out
standard cat took 1.968000 seconds
big buffer cat took 1.891000 seconds
*/
Mar 6 '08 #15
On Mar 6, 12:35*pm, user923005 <dcor...@connx.comwrote:
On Mar 6, 12:30*pm, user923005 <dcor...@connx.comwrote:


On Mar 5, 6:06*pm, Jag <talon....@gmail.comwrote:
I've read parts of K&R's ANSI C v2 and this is what their cat looked
like but when I compared the speed of this code to gnu cat, it seems
very slow. How do I optimize this for greater speeds? is there an
alternative algorithm?
void catfile(FILE *in, FILE *out) {
* * register int num_char;
* * /*Get characters*/
* * while ((num_char = getc(in)) != EOF) {
* * * * /*Print to standard output*/
* * * * putc(num_char, out);
* * }
}
C:\tmp>dir dict.sql
*Volume in drive C has no label.
*Volume Serial Number is 0890-87CA
*Directory of C:\tmp
03/01/2007 *11:48 AM * * * * 7,127,408 dict.sql
* * * * * * * *1 File(s) * * *7,127,408 bytes
* * * * * * * *0 Dir(s) * 5,202,309,120 bytes free
C:\tmp>cat dict.sql dict.out
standard cat took 1.984000 seconds
big buffer cat took 0.000000 seconds
C:\tmp>type cat.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void * * * * * *catfilebuffer(FILE * in, FILE * out)
{
* * register int * *num_char;
* * setvbuf(in, NULL, _IOFBF, 1024 * 16);
* * setvbuf(out, NULL, _IOFBF, 1024 * 16);
* * /* Get characters */
* * while ((num_char = getc(in)) != EOF) {
* * * * /* Print to standard output */
* * * * putc(num_char, out);
* * }
}
void * * * * * *catfilenobuff(FILE * in, FILE * out)
{
* * register int * *num_char;
* * /* Get characters */
* * while ((num_char = getc(in)) != EOF) {
* * * * /* Print to standard output */
* * * * putc(num_char, out);
* * }
}
int * * * * * * main(int argc, char **argv)
{
* * FILE * * * * * *in = stdin;
* * FILE * * * * * *out = stdout;
* * clock_t * * * * start,
* * * * * * * * * * end;
* * static const double *cps = 1.0 / CLOCKS_PER_SEC;
* * if (argc 1) {
* * * * in = fopen(argv[1], "r");
* * * * if (in == NULL) {
* * * * * * printf("Error opening %s\n", argv[1]);
* * * * * * exit(EXIT_FAILURE);
* * * * }
* * }
* * if (argc 2) {
* * * * out = fopen(argv[2], "w");
* * * * if (out == NULL) {
* * * * * * printf("Error opening %s\n", argv[2]);
* * * * * * exit(EXIT_FAILURE);
* * * * }
* * }
* * start = clock();
* * catfilenobuff(in, out);
* * end = clock();
* * printf("standard cat took %f seconds\n", (end - start) * cps);
* * start = clock();
* * catfilebuffer(in, out);
* * end = clock();
* * printf("big buffer cat took %f seconds\n", (end - start) * cps);
* * fflush(NULL);
* * return 0;
}- Hide quoted text -
- Show quoted text -

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void * * * * * *catfilebuffer(FILE * in, FILE * out)
{
* * register int * *num_char;

* * setvbuf(in, NULL, _IOFBF, 1024 * 16);
* * setvbuf(out, NULL, _IOFBF, 1024 * 16);

* * /* Get characters */
* * while ((num_char = getc(in)) != EOF) {
* * * * /* Print to standard output */
* * * * putc(num_char, out);
* * }

}

void * * * * * *catfilenobuff(FILE * in, FILE * out)
{
* * register int * *num_char;

* * /* Get characters */
* * while ((num_char = getc(in)) != EOF) {
* * * * /* Print to standard output */
* * * * putc(num_char, out);
* * }

}

int * * * * * * main(int argc, char **argv)
{
* * FILE * * * * * *in = stdin;
* * FILE * * * * * *out = stdout;
* * clock_t * * * * start,
* * * * * * * * * * end;
* * static const double cps = 1.0 / CLOCKS_PER_SEC;
* * if (argc 1) {
* * * * in = fopen(argv[1], "r");
* * * * if (in == NULL) {
* * * * * * printf("Error opening %s\n", argv[1]);
* * * * * * exit(EXIT_FAILURE);
* * * * }
* * }
* * if (argc 2) {
* * * * out = fopen(argv[2], "w");
* * * * if (out == NULL) {
* * * * * * printf("Error opening %s\n", argv[2]);
* * * * * * exit(EXIT_FAILURE);
* * * * }
* * }
* * start = clock();
* * catfilenobuff(in, out);
* * end = clock();
* * printf("standard cat took %f seconds\n", (end - start) * cps);
* * rewind(in);
* * fclose(out);
* * if (argc 2) {
* * * * out = fopen(argv[2], "w");
* * * * if (out == NULL) {
* * * * * * printf("Error opening %s\n", argv[2]);
* * * * * * exit(EXIT_FAILURE);
* * * * }
* * } else
* * * * out = stdout;
* * start = clock();
* * catfilebuffer(in, out);
* * end = clock();
* * printf("big buffer cat took %f seconds\n", (end - start) * cps);
* * fflush(NULL);
* * return 0;}

/*
Not nearly so dramatic! ;-)
C:\tmp>cat dict.sql dict.out
standard cat took 1.968000 seconds
big buffer cat took 1.891000 seconds
*/- Hide quoted text -

- Show quoted text -
The real problem here is that catfilebufferfgets() needs to be made
much more robust. But it does lend a lot of speed (probably due to
the much lower number of function calls and tests).

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static char string[1024 * 16];

void catfilebufferfgets(FILE * in, FILE * out)
{
setvbuf(in, NULL, _IOFBF, 1024 * 16);
setvbuf(out, NULL, _IOFBF, 1024 * 16);

/* Get characters (ERROR PRONE: {what if string 16K}) */
while (fgets(string, sizeof string, in)) {
fputs(string, out);
}
}

void catfilebuffer(FILE * in, FILE * out)
{
register int num_char;

setvbuf(in, NULL, _IOFBF, 1024 * 16);
setvbuf(out, NULL, _IOFBF, 1024 * 16);

/* Get characters */
while ((num_char = getc(in)) != EOF) {
/* Print to standard output */
putc(num_char, out);
}
}

void catfilenobuff(FILE * in, FILE * out)
{
register int num_char;

/* Get characters */
while ((num_char = getc(in)) != EOF) {
/* Print to standard output */
putc(num_char, out);
}
}

int main(int argc, char **argv)
{
FILE *in = stdin;
FILE *out = stdout;
clock_t start,
end;
static const double cps = 1.0 / CLOCKS_PER_SEC;
if (argc 1) {
in = fopen(argv[1], "r");
if (in == NULL) {
printf("Error opening %s\n", argv[1]);
exit(EXIT_FAILURE);
}
}
if (argc 2) {
out = fopen(argv[2], "w");
if (out == NULL) {
printf("Error opening %s\n", argv[2]);
exit(EXIT_FAILURE);
}
}
start = clock();
catfilenobuff(in, out);
end = clock();
printf("standard cat took %f seconds\n", (end - start) * cps);
rewind(in);
fclose(out);
if (argc 2) {
out = fopen(argv[2], "w");
if (out == NULL) {
printf("Error opening %s\n", argv[2]);
exit(EXIT_FAILURE);
}
} else
out = stdout;
start = clock();
catfilebuffer(in, out);
end = clock();
printf("big buffer cat took %f seconds\n", (end - start) * cps);
rewind(in);
fclose(out);
if (argc 2) {
out = fopen(argv[2], "w");
if (out == NULL) {
printf("Error opening %s\n", argv[2]);
exit(EXIT_FAILURE);
}
} else
out = stdout;
start = clock();
catfilebufferfgets(in, out);
end = clock();
printf("big buffer cat using fgets took %f seconds\n", (end -
start) * cps);
fflush(NULL);
return 0;
}
/*
C:\tmp>cat dict.sql dict.out
standard cat took 2.062000 seconds
big buffer cat took 2.016000 seconds
big buffer cat using fgets took 0.203000 seconds
*/
Mar 6 '08 #16
On Mar 6, 12:44*pm, user923005 <dcor...@connx.comwrote:
[snip]
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static char * * string[1024 * 16];

void * * * * * *catfilebufferfgets(FILE * in, FILE * out)
{
* * setvbuf(in, NULL, _IOFBF, 1024 * 16);
* * setvbuf(out, NULL, _IOFBF, 1024 * 16);

* * /* Get characters (ERROR PRONE: {what if string 16K}) */
* * while (fgets(string, sizeof string, in)) {
* * * * fputs(string, out);
* * }

}
[snip]
/*
C:\tmp>cat dict.sql dict.out
standard cat took 2.062000 seconds
big buffer cat took 2.016000 seconds
big buffer cat using fgets took 0.203000 seconds
*/

Another important difference is that the fgets() version only works on
text files (for obvious reasons).
Mar 6 '08 #17
SM Ryan wrote:
>
.... snip bad quote marks ...
>
The system cat exploits features of the specific system that
are not available in ANSI C. For example on unix, you can
avoid stdio altogether, and do something like
read -shared buffer -write
You can largely do that in ANSI C, with streams. Just use getc()
and putc(). This is why these routines can be implemented as
macros. The time cost of transferring a buffer content must be
negligible compared with the cost of reading/writing disk (or
other) files.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Mar 6 '08 #18
Jag
On Mar 6, 8:49 pm, user923005 <dcor...@connx.comwrote:
On Mar 6, 12:44 pm, user923005 <dcor...@connx.comwrote:
[snip]
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static char string[1024 * 16];
void catfilebufferfgets(FILE * in, FILE * out)
{
setvbuf(in, NULL, _IOFBF, 1024 * 16);
setvbuf(out, NULL, _IOFBF, 1024 * 16);
/* Get characters (ERROR PRONE: {what if string 16K}) */
while (fgets(string, sizeof string, in)) {
fputs(string, out);
}
}
[snip]
/*
C:\tmp>cat dict.sql dict.out
standard cat took 2.062000 seconds
big buffer cat took 2.016000 seconds
big buffer cat using fgets took 0.203000 seconds
*/

Another important difference is that the fgets() version only works on
text files (for obvious reasons).
This code, like cat -n and cat -e outputs the line number or adds a $
at the end of the line. getline is a gnu extension.I haven't used
setvbuf before. what does it do? anyway, without setvbuf(), it
resulted into 2.580000 seconds but with setvbuf(), it resulted into
1.230000 seconds. Thanks for the tip :)

int catline(FILE *in, FILE *out, int nCounter,
bool const bLine, bool const bEnds) {

char *pLine = NULL;
size_t pLen = 0;

setvbuf(in, NULL, _IOFBF, BUFSIZ);
setvbuf(out, NULL, _IOFBF, BUFSIZ);

while (!feof(in)) {
/*Get line*/
if (getline(&pLine, &pLen, in) >= 0) {

if (bLine == true)
/*Print string to standard output*/
fprintf(out, "%6d %s", nCounter, pLine);
/*Remove '\n' add a $ at the end of the line*/
else if (bEnds == true) {
if (pLine[strlen(pLine) - 1] == '\n') {
pLine[strlen(pLine) - 1] = pLine[strlen(pLine)];
pLine[strlen(pLine)] = '\0';
fprintf(out, "%s$\n", pLine);
}
/*If there is no '\n' at the end of the line add a $
without a '\n'*/
else
fprintf(out, "%s$", pLine);
}

/*Increment line counter*/
++nCounter;
}
}
/*Free allocated memory in getline()*/
free(pLine);

return(nCounter);
}
Mar 7 '08 #19
Jag
On Mar 6, 8:49 pm, user923005 <dcor...@connx.comwrote:
On Mar 6, 12:44 pm, user923005 <dcor...@connx.comwrote:
[snip]
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static char string[1024 * 16];
void catfilebufferfgets(FILE * in, FILE * out)
{
setvbuf(in, NULL, _IOFBF, 1024 * 16);
setvbuf(out, NULL, _IOFBF, 1024 * 16);
/* Get characters (ERROR PRONE: {what if string 16K}) */
while (fgets(string, sizeof string, in)) {
fputs(string, out);
}
}
[snip]
/*
C:\tmp>cat dict.sql dict.out
standard cat took 2.062000 seconds
big buffer cat took 2.016000 seconds
big buffer cat using fgets took 0.203000 seconds
*/

Another important difference is that the fgets() version only works on
text files (for obvious reasons).
Oh, I also used setvbuf() in my original post and yielded: no
setvbuf() 2.440000, with setvbuf(), 0.920000.
WOW.

void catfile(FILE *in, FILE *out) {
register int num_char;

setvbuf(in, NULL, _IOFBF, BUFSIZ);
setvbuf(out, NULL, _IOFBF, BUFSIZ);

/*Get characters*/
while ((num_char = getc(in)) != EOF) {
/*Print to standard output*/
putc(num_char, out);
}
}
Mar 7 '08 #20
Jag wrote:
I've read parts of K&R's ANSI C v2 and this is what their cat looked
like but when I compared the speed of this code to gnu cat, it seems
very slow. How do I optimize this for greater speeds? is there an
alternative algorithm?

void catfile(FILE *in, FILE *out) {
register int num_char;

/*Get characters*/
while ((num_char = getc(in)) != EOF) {
/*Print to standard output*/
putc(num_char, out);
}
}

Thanks.
It's fairly inefficient to get characters one by one. If you felt like
using system calls to do it, you could use read(), but then you couldn't
use FILE *. However, the only thing you really need to do is increase
your buffer size (from one), and thus you could use fgets(). 4096
bytes, if I recall, is a fairly standard block size; it's the most
efficient to read full blocks at a time.

Remember to initialise your variables!

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

void catfile(FILE * in, FILE * out) {
char * buf = (char *)malloc(4097); //4096 + 1 for \0
if (!buf) exit(-1);
register int num_char = 0;

while (!feof(in)) {
if (!fgets(buf, 4097, in)) break;
num_char += strlen(buf);
fprintf(out, "%s", buf);
};

free(buf);
};

--
--Falcon Kirtaran
Mar 7 '08 #21
Falcon Kirtaran said:

<snip>
>
It's fairly inefficient to get characters one by one. [...]
However, the only thing you really need to do is increase
your buffer size (from one), and thus you could use fgets().
Typically, input is buffered by default, so it doesn't actually make any
difference.

I compiled your function (after translating it into C90), removed the
spurious semicolon, and added a main. I then used it to cat a 4MB JPEG.

real 0m1.484s
user 0m0.010s
sys 0m0.210s

Compare:

void catfile(FILE * in, FILE * out) {
int ch;
while((ch = getc(in)) != EOF)
{
putc(ch, out);
}
}

real 0m0.633s
user 0m0.540s
sys 0m0.070s

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Mar 7 '08 #22
On Thu, 6 Mar 2008 08:38:09 UTC, Micah Cowan <mi***@micah.cowan.name>
wrote:
Richard Heathfield <rj*@see.sig.invalidwrites:
If that's what you mean, then my answer is:
- It's not appreciably harder to add braces later than it is to put
them in in the first place.
Agreed. BUT - it is appreciably harder to remember to add them later on
special occasions than to put them in every time as a matter of habit.

Hm. I haven't found it to be so.

while (c)
c=do_it(c);
c=do_another_thing(c);

looks too broken right away for me not to notice it (though, perhaps
now that I'm doing more Python coding work these days, that may
change?).

I used to actually always put the braces in. I've fallen out of that
practice, just because I find it slightly more readable without, for
one-line bodies.
Uh, a halfways intelligent editor will help in writing/editing source.

So my editor is set up expanding 'while' to

while (_) {
}

setting the cursor at the position represented by the underline
charater. Leaving the condition with TAB will insert an empty line,
placing the cursor in the new linedirectly under the 'l' from while,
so new indent is done, ready to type. Enter will insert a new line,
holding the same indent. Shift Enter in insert mode will insert a new
line under the closing bracket and the cursor under it.

Equivalence is given for do, for an so on magically. So conditional
blocks are magically written, indending is done automatically.

The behavior of enter, TAB and opening brace characters changes
depending on the insert|override mode, Enter, shift enter, Ctrl Enter
and Alöt Enter have different mode too. So typing a new program gets
easy, edit it too.

So leaving a block off from typing is at least more hard than having
it already. Indent is set magically, so misleading gets harder having
it right.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
Mar 9 '08 #23

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: William C. White | last post by:
Does anyone know of a way to use PHP /w Authorize.net AIM without using cURL? Our website is hosted on a shared drive and the webhost company doesn't installed additional software (such as cURL)...
2
by: Albert Ahtenberg | last post by:
Hello, I don't know if it is only me but I was sure that header("Location:url") redirects the browser instantly to URL, or at least stops the execution of the code. But appearantely it continues...
3
by: James | last post by:
Hi, I have a form with 2 fields. 'A' 'B' The user completes one of the fields and the form is submitted. On the results page I want to run a query, but this will change subject to which...
0
by: Ollivier Robert | last post by:
Hello, I'm trying to link PHP with Oracle 9.2.0/OCI8 with gcc 3.2.3 on a Solaris9 system. The link succeeds but everytime I try to run php, I get a SEGV from inside the libcnltsh.so library. ...
1
by: Richard Galli | last post by:
I want viewers to compare state laws on a single subject. Imagine a three-column table with a drop-down box on the top. A viewer selects a state from the list, and that state's text fills the...
4
by: Albert Ahtenberg | last post by:
Hello, I have two questions. 1. When the user presses the back button and returns to a form he filled the form is reseted. How do I leave there the values he inserted? 2. When the...
1
by: inderjit S Gabrie | last post by:
Hi all Here is the scenerio ...is it possibly to do this... i am getting valid course dates output on to a web which i have designed ....all is okay so far , look at the following web url ...
2
by: Jack | last post by:
Hi All, What is the PHP equivilent of Oracle bind variables in a SQL statement, e.g. select x from y where z=:parameter Which in asp/jsp would be followed by some statements to bind a value...
3
by: Sandwick | last post by:
I am trying to change the size of a drawing so they are all 3x3. the script below is what i was trying to use to cut it in half ... I get errors. I can display the normal picture but not the...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.