Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Apr 2006 02:03:01 +0200
From:      Benjamin Lutz <benlutz@datacomm.ch>
To:        freebsd-chat@freebsd.org
Cc:        Dan Strick <strick@covad.net>
Subject:   Re: Why is not more FreeBSD software written in C++?
Message-ID:  <200604230203.05209.benlutz@datacomm.ch>
In-Reply-To: <200604221511.k3MFBxa2003218@mist.nodomain>
References:  <200604221511.k3MFBxa2003218@mist.nodomain>

next in thread | previous in thread | raw e-mail | index | archive | help
--nextPart1297295.LFSzQG6KxA
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

On Saturday 22 April 2006 17:11, Dan Strick wrote:
> On Friday 21 Apr 2006 09:20, Don Dugger wrote:
> > The example above is not exactly a realworld example. Even if you stick
> > to  plain C, a repeated putchar(' ') is 1-2 orders of magnitude slower
> > than aggregating those characters and write()'ing them every few dozen
> > chars.
>
> This might seem obvious, but is it really true?  I wrote a program that
> tries it both ways with the output redirected to /dev/null and discovered
> that filling a 24 character buffer and doing a write() takes about 11 tim=
es
> as much cpu time as 24 putchar()s.  Perhaps a buffer larger than a "few
> dozen chars" would be useful.  There must be a moral here somewhere.  :-)

Yes, it is really true. Since I don't know what your test is, I've created =
my=20
own.

test_putchar.c:=20
=2D---
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv) {
        int i, j;
        for (i =3D 0; i < 50000; i++) {
                for (j =3D 0; j < 60; j++) {
                        putchar('.');
                }
                putchar('\n');
        }
        return 0;
}
=2D---

test_write.c:
=2D---
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char** argv) {
        char buf[61];
        int i, j;
        for (i =3D 0; i < 50000; i++) {
                for (j =3D 0; j < 60; j++) {
                        buf[j] =3D '.';
                }
                buf[60] =3D '\n';
                write(STDOUT_FILENO, buf, 61);
        }
        return 0;
}
=2D---
And for completeness' sake, two corresponding C++ iostream variants:
test_iostream.cpp:
=2D---
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
        for (int i =3D 0; i < 50000; i++) {
                for (int j =3D 0; j < 60; j++) {
                        cout << '.';
                }
                cout << '\n';
        }
        return 0;
}
=2D---

test_string.cpp
=2D---
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
        for (int i =3D 0; i < 50000; i++) {
                for (int j =3D 0; j < 60; j++) {
                        cout << '.';
                }
                cout << '\n';
        }
        return 0;
}
=2D---

All files are compiled with gcc/g++ and the -O2 option. I'm running them on=
 a=20
Mac Mini under Linux.

And the results are (I've run that command several times and picked a line=
=20
that shows an average run time):

$ time ./test_putchar > /dev/null
=2E/test_putchar > /dev/null  0.39s user 0.00s system 97% cpu 0.397 total
$ time ./test_write > /dev/null
=2E/test_write > /dev/null  0.02s user 0.01s system 82% cpu 0.029 total
$ time ./test_iostream > /dev/null
=2E/test_iostream > /dev/null  0.94s user 0.00s system 99% cpu 0.950 total
$ time ./test_string > /dev/null
=2E/test_string > /dev/null  0.21s user 0.00s system 97% cpu 0.213 total


That quite clearly shows that my prediction that using putchar is "1-2 orde=
rs=20
of magnitude slower" is accurate. It also shows the points you and others=20
have made that iostream is slower than C's I/O mechanisms.

If we take the two most sensible variants, test_write and test_iostream, an=
d=20
have them write into a file, we get these numbers:

$ time ./test_write > foo
=2E/test_write > foo  0.01s user 0.16s system 95% cpu 0.180 total
$ time ./test_string > foo
=2E/test_string > foo  0.20s user 0.02s system 98% cpu 0.223 total

Which is a small enough difference to be irrelevant. The large I/O performa=
nce=20
advantage of the write(2) variant over the C++ string variant vanishes as=20
soon as the code actually does something remotely useful.

> I am not claiming that strings and iostreams are bad.  I am observing
> that some reasonable programs that use these facilities will run very
> slowly and I am suggesting that it is not always obvious which programs
> these are.

You mentioned a pretty printer. I'm not convinced that the performance=20
drawbacks you saw were inherent in iostream. Rather it seems that the comfo=
rt=20
of C++'s strings and streams led the programmer to program in a less=20
performance-conscious way.

> I am also expressing disappointment because I want the=20
> decision to use any feature of C++ or its standard library to be a
> no-brainer.

Personally, I don't hesitate to use features of C++. As for the STL... ther=
e=20
are nice alternatives that are sometimes available. When writing Qt program=
s,=20
I'll use Qt's data structures only, not the STL ones, since imo Qt's data=20
structure classes are more comfortable to use.

Cheers
Benjamin

--nextPart1297295.LFSzQG6KxA
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.2 (GNU/Linux)

iD8DBQBESsQ5gShs4qbRdeQRAlIlAJ4hGnBtg4OiW8BpCuFWVI9ujIqW9ACeJ7wu
l6InmUPeDNGdO6aiIz+V8yk=
=pUhW
-----END PGP SIGNATURE-----

--nextPart1297295.LFSzQG6KxA--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200604230203.05209.benlutz>