Help me, a friend of mine wrote a program in C# and I wrote the sameprogram in C..His is faster than

C

c

Thanks sir for you reply..
you mentioned "It appears that your friend has a
faster disk than you do"
We both have the same laptop..same model..anyway, I tested my program
in his laptop just in case..
anyway, I compiled the code you posted..its save a 0-byte text file on
machine..
I will try with another compiler..I'll get back to you..

If your disk drives are the same, that indicates that the buffered I/O
of C# is superior to the buffered I/O of C.

You must have compiled the second program, which does not write
anything to disk.
The first program writes a 160 MB file.

Here is a very cheesy alternative:

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

unsigned fact(unsigned n)
{
unsigned result = 1;
while (n-- > 1)
result *= n;
return result;

}

static char absurd_buffer[160000000];

int main(void)
{
FILE *fp;
unsigned loop;
if ((fp = fopen("log.txt", "w")) != NULL) {

if (setvbuf(fp, absurd_buffer, _IOFBF, sizeof absurd_buffer) !
= 0) {
int e = errno;
puts(strerror(e));
printf("Incorrect type or size of buffer for log.txt.
Value of errno is %d.\n", e);
}
for (loop = 1; loop <= 10000000; loop++) {
fprintf(fp, "%u\n", fact(10));
}
fclose(fp);
}
return 0;

}

I compiled you code with Borland C++ and used the option "optimize for
speed"
bcc32.exe -O2 fact.c

and Compiled the C# code, which uses recursion. yours doesn't

all on one Computer, the same Computer...all on his laptop..

guess what..his is faster, way faster...I tried all of the code posted
on this article...every single code you guys posted...he still
faster...and way faster...

but under Slackware..any code will be faster, even stupid code....
with recursion or with out..
 
K

Keith Thompson

c said:
and then we decided to write a program that will calculate the
factorial of 10, 10 millions time and print the reusult in a file with
the name log.txt..

I wrote something like this

#include <stdio.h>
unsigned int fib (int n);



int main()
{
FILE *fp;
unsigned int loop =1 ;
if ( (fp = fopen( "log.txt", "a" )) != NULL )
for (loop; loop <= 10000000 ; loop++)
{

fprintf(fp,"%u\n",fib(10));
}
fclose (fp);
return 0;
}



unsigned int fib (int n)
{ if (n != 1 )
return n * fib(n-1);
else
return 1;
}
[snip]

As others have mentioned, you don't actually seem to be measuring your
fib() (should be called fact() or factorial()) function.

On my system, your program ran in 4.98 seconds. When I changed the
line
fprintf(fp,"%u\n",fib(10));
to
fprintf(fp, "%u\n", 3628800u);
it ran in 5.27 seconds.

I don't believe the apparent slowdown is significant; it's probably
with the margin of error of my measurement. But it suggests that the
performance of the program is dominated by writing 153 megabytes (!)
of output.

If you really want to measure the speed of the computations, don't
intersperse it with I/O.
 
K

Keith Thompson

Tor Rustad said:
Methinks, you are not really measuring program speed, but I/O performance.

You was printing '3628800' 10 million times, that's only 7 bytes per I/O.

In C, try using fwrite() instead, and issue only one I/O per 4 kb,
even better should be one I/O per 64 kb. If doing that, I guess you
drop below 2 seconds on XP.

I doubt it. Output using stdio is buffered; most of those fprintf
calls are just writing to memory. Probably the overhead of fprintf
processing the format string is significant; I just sped it up by a
factor of 3 or so by using fputs() rather than fprintf() (with a
constant string in both cases).

Actually, that could be an interesting exercise: find out where the
program is really spending its time. (Note that such an exercise
isn't necessarily topical here in comp.lang.c.)
 
T

Tor Rustad

As others have mentioned, you don't actually seem to be measuring your
fib() (should be called fact() or factorial()) function.

On my system, your program ran in 4.98 seconds. When I changed the
line
fprintf(fp,"%u\n",fib(10));
to
fprintf(fp, "%u\n", 3628800u);
it ran in 5.27 seconds.

Yeah, as expected, an IO bound problem this.
I don't believe the apparent slowdown is significant; it's probably
with the margin of error of my measurement. But it suggests that the
performance of the program is dominated by writing 153 megabytes (!)
of output.

Keith, may you explain how is writing 7 bytes 10 million times,
generating a 153 Mb file on your system?

Did you run the program twice? ;-)
 
T

Tor Rustad

I doubt it. Output using stdio is buffered; most of those fprintf
calls are just writing to memory.

Well, I can check it, when getting back from work. After doing some
code changes,
I'm 99% sure my version will run below 2 seconds on my laptop, the
Fujitsu 2.5-inch
SATA HD there have specs for 150 MB/s! :)

Regarding 7 bytes fprintf(), odd plus odd is even, even plus odd is
odd. So
it goes 10 million times, that's at least 5 million non-optimal
memory
accesses...

Perhaps, the bottleneck on most systems is the disk-subsystem, but
the least we can do, is make sure that every IO is accessing
aligned memory, and change buffer from 7 bytes to something bigger
(e.g. 64 kb).
 
J

Johannes Bauer

c said:
unsigned int fib (int n)
{ if (n != 1 )
return n * fib(n-1);
else
return 1;
}


and he did the something in C#

1. Use the itarative variant, as was pointed out.
2. Mark the function "const"!

I wonder why nobody has pointed out #2 so far - probably because it's
not a language thing, but a compiler specification. When using gcc, it
will work, it might with other compilers as well. When optimization is
used it will make your program run like hell, as the factorial is only
calculated one single time. Kind of unfair, yes, but a cool
optimization. And you're comparing apples to oranges anyways, so...

Define/declare your function like this

#include <stdio.h>

unsigned fact(unsigned n) __attribute__((const));

unsigned fact(unsigned n) {
unsigned result = 1;
while (n-- > 1) result *= n;
return result;
}

int main() {
int i;
for (i = 0; i < 1000000; i++) {
printf("%d\n", fact(10));
}
return 0;
}


Greetings,
Johannes
 
C

Chris Dollin

Johannes said:
1. Use the itarative variant, as was pointed out.
2. Mark the function "const"!

I wonder why nobody has pointed out #2 so far - probably because it's
not a language thing, but a compiler specification.
Exactly.

When using gcc, it
will work, it might with other compilers as well. When optimization is
used it will make your program run like hell,

Haven't various posters established that the time /of the program being
tested/ is dominated by /output/? Having fact-misnamed-fib take /zero
time/ won't help appreciably.
 
J

Johannes Bauer

Chris said:
Haven't various posters established that the time /of the program being
tested/ is dominated by /output/? Having fact-misnamed-fib take /zero
time/ won't help appreciably.

Well, a value greater than "10" would probably be useful in order to
calculate the time actually spent in the factorial function. Then again,
it depends on what you actually want to measure. It's apples and
oranges, as I said.

Greetings,
Johannes
 
C

Chris Dollin

Johannes said:
Well, a value greater than "10" would probably be useful in order to
calculate the time actually spent in the factorial function.

No, to calculate the time spent in the factorial function one needs
to measure the time spent /in that function/, not doing output, which
is what the OP was doing. (Whether or not they and their friend /meant/
to compare output speeds, that seems to be what they've done.)
Then again, it depends on what you actually want to measure.
It's apples and oranges, as I said.

Two members of the same family, then?
 
G

Gus Gassmann

Hi every one,

Me and my Cousin were talking about C and C#, I love C and he loves
C#..and were talking C is ...blah blah...C# is Blah Blah ...etc

and then we decided to write a program that will calculate the
factorial of 10, 10 millions time and print the reusult in a file with
the name log.txt..

I wrote something like this

#include <stdio.h>
unsigned int fib (int n);

int main()
{
FILE *fp;
unsigned int loop =1 ;
if ( (fp = fopen( "log.txt", "a" )) != NULL )
for (loop; loop <= 10000000 ; loop++)
{

fprintf(fp,"%u\n",fib(10));
}
fclose (fp);
return 0;

}

unsigned int fib (int n)
{ if (n != 1 )
return n * fib(n-1);
else
return 1;
}

Since everything here is hard-wired, why not simply:

#include <stdio.h>

int main()
{
FILE *fp;
unsigned int loop =1 ;
if ( (fp = fopen( "log.txt", "a" )) != NULL )
for (loop; loop <= 10000000 ; loop++)
{
fprintf(fp,"3628800\n");
}
fclose (fp);
return 0;
}

I betcha that's faster than the recursion...
 
N

Neil Cerutti

I ran my program, I took 18 seconds to get done..his program
took 7 seconds..Wow

His program is probably buggy. Write another C program to verify
that his program's output is identical to yours.
 
K

Keith Thompson

Tor Rustad said:
Keith, may you explain how is writing 7 bytes 10 million times,
generating a 153 Mb file on your system?

Did you run the program twice? ;-)

Yes, I did -- without noticing that the "log.txt" file is opened in
append mode. (Apparently when you're writing 3628800 ten million
times, it's important not to overwrite the previous ten million
occurrences of 3628800.)
 
K

Keith Thompson

Tor Rustad said:
Regarding 7 bytes fprintf(), odd plus odd is even, even plus odd is
odd. So it goes 10 million times, that's at least 5 million
non-optimal memory accesses...

Perhaps, the bottleneck on most systems is the disk-subsystem, but
the least we can do, is make sure that every IO is accessing
aligned memory, and change buffer from 7 bytes to something bigger
(e.g. 64 kb).

The output statement is
fprintf(fp,"%u\n",fib(10));
where fib(10) is 3628800, so that's 7 digits *plus a new-line*. If a
new-line is written as a single character, that's 8 bytes per call.
 
T

Tor Rustad

Keith said:
The output statement is
fprintf(fp,"%u\n",fib(10));
where fib(10) is 3628800, so that's 7 digits *plus a new-line*. If a
new-line is written as a single character, that's 8 bytes per call.

Oooops, right... I didn't notice that new-line! *red-face*

However, 1 byte new-line is a UNIX thing, on Windows it's usually two
bytes, so my point still hold. ;-)


I did a benchmark, the best IO result was doing the
"Standard C IO no buffering" call, each fwrite() call
used buffer with 64 kb of data. Re-running the same
bench under Linux gave quite a suprise (see below)!!!


On Windows XP I got:

printing '3628800' 10 million times
------------------------------
Standard C IO by OP
Written 1220 pages of ca. size 65536 (80000000 bytes)
CPU time 7.03
DiskIO 11.11 Mb/s
------------------------------
Standard C IO
Written 1221 pages of ca. size 65536 (80019456 bytes)
CPU time 4.36
DiskIO 17.93 Mb/s
------------------------------
Standard C IO no buffering
Buffering turned off
Written 1221 pages of ca. size 65536 (80019456 bytes)
CPU time 2.53
DiskIO 30.86 Mb/s


$ gcc challenge.c stdio_c.c -O3
$ time ./a.out
printing '3628800' 10 million times
------------------------------
Standard C IO by OP
Written 1220 pages of ca. size 65536 (80000000 bytes)
CPU time 2.74
DiskIO 28.51 Mb/s
------------------------------
Standard C IO
Written 1221 pages of ca. size 65536 (80019456 bytes)
CPU time 0.27
DiskIO 289.42 Mb/s
------------------------------
Standard C IO no buffering
Buffering turned off
Written 1221 pages of ca. size 65536 (80019456 bytes)
CPU time 0.26
DiskIO 300.55 Mb/s

real 0m7.834s
user 0m2.528s
sys 0m0.756s


300.55 Mb/s is too good, the theoretical peek should
have been 150 Mb/s, I don't know why Linux is this
blitzing fast! Does it have anything to do with dual
core CPU??? *strange*


/*-------------- listing 'challenge.c' ------------------------*/

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <assert.h>

#define FILE_NAME "log.txt"
#define IO_BLOCK_SIZE (64*1024)

unsigned int fac(int n)
{
if (n != 1)
return n * fac(n - 1);
else
return 1;
}

/* make_io_buf: from number 'u', fill a buffer with this value 'count' times
* return lenght of buffer
*/
static size_t make_io_buf(char *buf, size_t max_buf, size_t * count,
unsigned u)
{
int n, len;
unsigned char u_buf[32];

n = sprintf(u_buf, "%u\n", u);
assert(n == 8);

/* fill up the buffer */
for (len = 0; len + n <= (int)max_buf; len += n) {
strcpy(&buf[len], u_buf);
*count = *count + 1;
}
assert(len <= max_buf);
assert(len + n > max_buf);

return len;
}

static void print_diff(clock_t start, clock_t stop, size_t wr_cnt)
{
double s = (double)(stop - start) / CLOCKS_PER_SEC,
Mb = (double)wr_cnt / 1024000.0;

printf("Written %lu pages of ca. size %d (%lu bytes)\n",
wr_cnt / IO_BLOCK_SIZE, IO_BLOCK_SIZE, wr_cnt);
printf("CPU time %.2f\n", s);
printf("DiskIO %.2f Mb/s\n", Mb / s);
}

extern int stdio_op(const char *fname, const unsigned char *buf,
size_t buf_len);
extern int stdio_c(const char *fname, const unsigned char *buf, size_t
buf_len);
extern int stdio_nobuf(const char *fname, const unsigned char *buf,
size_t buf_len);

int main(void)
{
static unsigned char buffer[IO_BLOCK_SIZE];
size_t buf_len = 0, count = 0, wr_cnt = 0;
clock_t start, stop;

printf("printing '%u' 10 million times\n", fac(10));

printf("------------------------------\nStandard C IO by OP\n");
start = clock();
wr_cnt = stdio_op(FILE_NAME, NULL, 0);
stop = clock();
print_diff(start, stop, wr_cnt);

printf("------------------------------\nStandard C IO\n");
start = clock();
buf_len = make_io_buf(buffer, sizeof buffer, &count, fac(10));
wr_cnt = stdio_c(FILE_NAME, buffer, buf_len);
stop = clock();
print_diff(start, stop, wr_cnt);

printf("------------------------------\nStandard C IO no buffering\n");
start = clock();
buf_len = make_io_buf(buffer, sizeof buffer, &count, fac(10));
wr_cnt = stdio_nobuf(FILE_NAME, buffer, buf_len);
stop = clock();
print_diff(start, stop, wr_cnt);

remove( FILE_NAME );

return 0;
}

/*-------------- listing stdio_c.c ------------------------*/

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

int stdio_op(const char *fname, const unsigned char *buf, size_t buf_len)
{
FILE *fp;
unsigned int loop, n=0;

if ( (fp = fopen( "log.txt", "a" )) != NULL )
for (loop=1; loop <= 10000000 ; loop++)
{
n += fprintf(fp,"%u\n",fac(10));
}
fclose (fp);

return n;
}

int stdio_c(const char *fname, const unsigned char *buf, size_t buf_len)
{
FILE *fp;
size_t loop
, count = buf_len / 8;
int wr_cnt = 0;


if ((fp = fopen(fname, "w+b")) != NULL) {

for (loop = 0; loop <= 10000000; loop += count) {
wr_cnt += fwrite(buf, 1, buf_len, fp);
}
fclose(fp);
}
return wr_cnt;
}

int stdio_nobuf(const char *fname, const unsigned char *buf, size_t buf_len)
{
FILE *fp;
size_t loop
, count = buf_len / 8;
int wr_cnt = 0;


if ((fp = fopen(fname, "w+b")) != NULL) {

if(0 == setvbuf(fp, NULL, _IONBF, 0 ))
puts( "Buffering turned off" );

for (loop = 0; loop <= 10000000; loop += count) {
wr_cnt += fwrite(buf, 1, buf_len, fp);
}
fclose(fp);
}
return wr_cnt;
}
 
S

Stephen Sprunk

Tor Rustad said:
Standard C IO no buffering
Buffering turned off
Written 1221 pages of ca. size 65536 (80019456 bytes)
CPU time 0.26
DiskIO 300.55 Mb/s ....
300.55 Mb/s is too good, the theoretical peek should
have been 150 Mb/s, I don't know why Linux is this
blitzing fast! Does it have anything to do with dual
core CPU??? *strange*

The speed you're measuring is how fast the fwrite() call returns, not the
disk write performance. Most likely, fwrite() returns after putting the
data into a buffer but before the hardware actually acknowledges it's been
written to disk. Modern OSes do all sorts of things like that to improve
performance.

S
 
B

Bart C

and then we decided to write a program that will calculate the
factorial of 10, 10 millions time and print the reusult in a file with
the name log.txt..

Your code ran in some 30 seconds on my (slowish) machine, and in about 1
second when I took out the fprintf() and only assigned the result of fib().
95% of of your run time is printing a text file as has been mentioned.

I'm surprised the results differ by as little as 7 seconds and 18 seconds.
If both run under Windows then C# is likely to have streamlined access to
low-level file i/o.

Make the test fairer by testing the algorithm only if you are testing the
code generation of C and C#. File i/o speed is more a test of libraries and
access to the OS.

Also you haven't given the source of the C# code, that might give extra
clues.

Bart
 
T

Tor Rustad

Stephen said:
The speed you're measuring is how fast the fwrite() call returns, not
the disk write performance. Most likely, fwrite() returns after putting
the data into a buffer but before the hardware actually acknowledges
it's been written to disk. Modern OSes do all sorts of things like that
to improve performance.

Nope, the clock was started *before* fopen(), and stopped *after*
fclose(). If Linux is using lazy commit, i.e. allowing a file to be e.g.
closed, before flushing system IO buffers, that would be highly
interesting/bad, particularly for those working with critical data.

Added another test case, this time using low-level POSIX IO functions
and sync'ing the file *before* close'ing it, the result was sky high IO,
434 Mb/s! So, the IO subsystem file writes is more than 10 times faster
on Linux, than under Windows XP, tests was done with identical HW and C
source.


*amazing*


$ ./a.out
printing '3628800' 10 million times
------------------------------
Standard C IO by OP
Written 1220 pages of ca. size 65536 (80000000 bytes)
CPU time 2.80
DiskIO 27.90 Mb/s
------------------------------
Standard C IO
Written 1221 pages of ca. size 65536 (80019456 bytes)
CPU time 0.28
DiskIO 279.09 Mb/s
------------------------------
Standard C IO no buffering
Buffering turned off
Written 1221 pages of ca. size 65536 (80019456 bytes)
CPU time 0.24
DiskIO 325.60 Mb/s
------------------------------
Low-level Linux IO
Written 1221 pages of ca. size 65536 (80019456 bytes)
CPU time 0.18
DiskIO 434.13 Mb/s


/*------- listing lowio_linux.c -----------------------*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

int lowio_linux(const char *fname, const unsigned char *buf, size_t buf_len)
{
unsigned int loop
, n = 0
, chunk = buf_len / 8;
int fd
, flags = O_WRONLY | O_CREAT | O_SYNC;
ssize_t rc;

fd = open(fname, flags, S_IRUSR | S_IWUSR);
if (fd != -1)
{
for (loop = 0; loop <= 10000000; loop+=chunk)
{
rc = write(fd, buf, buf_len);
if (rc == -1)
puts("write error"), exit(EXIT_FAILURE);
n += rc;
}
rc = fsync(fd);
if (rc == -1)
puts("fsync error"), exit(EXIT_FAILURE);
close(fd);
}

return n;
}
 
T

Tor Rustad

Tor Rustad wrote:

[...]
Added another test case, this time using low-level POSIX IO functions
and sync'ing the file *before* close'ing it, the result was sky high IO,
434 Mb/s! So, the IO subsystem file writes is more than 10 times faster
on Linux, than under Windows XP, tests was done with identical HW and C
source.


*amazing*


I knew something was *wrong*. Grrr... these numbers are not valid! Why?

What basic mistake did I do?


Hint: what do clock() measure, and where does the program spend the time?
 
S

Stephen Sprunk

Tor Rustad said:
Nope, the clock was started *before* fopen(), and stopped *after*
fclose().

fclose() just closes the FILE* (and related fd); it does _not_ guarantee
that the data is actually physically on the disk. There may be some
OS-specific function that will give you the indication you're wrongly
assuming you're getting, but it's not on by default.
If Linux is using lazy commit, i.e. allowing a file to be e.g. closed,
before flushing system IO buffers, that would be highly interesting/bad,
particularly for those working with critical data.

It's completely normal. That's why one should always shut down machines
cleanly instead of pulling the plug -- and why data (and filesystems) tend
to get corrupted when the power goes out. Even the disks lie to the OS
about when data is written; as soon as the data is in the drive's cache, it
tells the OS it's done writing so that the OS can reuse the buffer(s). Only
top-of-the-line controllers with battery-backed caches are immune from these
sorts of problems (and even then, you have to boot the machine again and let
it finish writing before removing the disk from the system).
Added another test case, this time using low-level POSIX IO
functions and sync'ing the file *before* close'ing it, the result was sky
high IO, 434 Mb/s! So, the IO subsystem file writes is more than 10
times faster on Linux, than under Windows XP, tests was done with
identical HW and C source.

*amazing*

It's not so amazing when you realize you're measuring the speed of the OS's
I/O system, not the hardware's.

S
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top