I've finally got Baby X (not the resource compiler, the Windows toolkit)
to link X11 on my Mac. And I can start work on it again. But it was far
from easyt to get it to link.
Can friendly people plesse dowload it and see if it compiles on other platforms?
I've finally got Baby X (not the resource compiler, the Windows toolkit) to link X11 on my Mac. And I can start work on it again. But it was far from easyt to get it to link.
Can friendly people plesse dowload it and see if it compiles on other platforms?
Am 11.06.2024 um 11:13 schrieb Malcolm McLean:
I've finally got Baby X (not the resource compiler, the Windows
toolkit) to link X11 on my Mac. And I can start work on it again. But
it was far from easyt to get it to link.
Can friendly people plesse dowload it and see if it compiles on other
platforms?
For large files it would be more convenient to have an .obj-output in
the proper format for Windows or Linux. I implemented a binary file to char-array compiler myself and for lage files the compilation time was totally intolerable and all the compilers I tested (g++, clang++, MSVC)
ran into out of memory conditiond sooner or later, depending on the
size of the char array.
Can friendly people plesse dowload it and see if it compiles on other platforms?
Am 11.06.2024 um 19:09 schrieb bart:
A char array initialised a byte at a time?
That is going to be inefficient.
xxd does is that way.
On 11/06/2024 15:16, Ben Bacarisse wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:Oh brilliant.
I've finally got Baby X (not the resource compiler, the Windows toolkit) to >>> link X11 on my Mac. And I can start work on it again. But it was far from >>> easyt to get it to link.Compiles and the test programs run on Ubuntu 24.04 (LTS).
Can friendly people plesse dowload it and see if it compiles on other
platforms?
Am 11.06.2024 um 18:15 schrieb Malcolm McLean:
These are Baby programs. But they use a cut down GUI. So they need to
get fonts and images into the program somehow. And so Baby X does that
by converting to 32 bit C arrays which can be compiled and linked as
normal. And for that, you need a tool. Writing a tiff file decoder is
not a trivial exercise.
I converted my code into sth. that produces a C-string as an output.
Printing that is still very fast, i.e. the files produced are written
with about 2.6GiB/s. But the problem is still that all compilers don't
parse large files but quit with an out of memory error. So having a
.obj output along with a small header file would be the best.
On 12/06/2024 07:40, Bonita Montero wrote:
I converted my code into sth. that produces a C-string as an output.
Printing that is still very fast, i.e. the files produced are written
with about 2.6GiB/s. But the problem is still that all compilers don't
parse large files but quit with an out of memory error. So having a
.obj output along with a small header file would be the best.
How big files are you talking about? In an earlier thread (which I
thought had beaten this topic to death), "xxd -i" include files were
fine to at least a few tens of megabytes with gcc.
 And it would be,
IMHO, absurd to have much bigger files than that embedded with your executable in this manner.
Am 12.06.2024 um 13:27 schrieb bart:
I suggested using a string representation. While the generated text
file is not much smaller, it is seen by the compiler as one string
expression, instead of millions of small expressions. Or at least,
1/20th the number if you split the strings across lines.
I implemented that with my second code but the compilers are still
limited with that.
Am 12.06.2024 um 15:13 schrieb bart:
I need another test with a 55MB test file. These are the results:
          {65,66,67,...     "\x41\x42\x43...
g++      284 seconds       13  seconds
tcc       20 seconds        2.5 seconds
I just tested this with my personal backup.
On 12/06/2024 08:01, David Brown wrote:
On 12/06/2024 07:40, Bonita Montero wrote:
I converted my code into sth. that produces a C-string as an output.
Printing that is still very fast, i.e. the files produced are written
with about 2.6GiB/s. But the problem is still that all compilers don't
parse large files but quit with an out of memory error. So having a
.obj output along with a small header file would be the best.
How big files are you talking about? In an earlier thread (which I
thought had beaten this topic to death), "xxd -i" include files were
fine to at least a few tens of megabytes with gcc.
What was never discussed is why xxd (and the faster alternates that
some posted to do that task more quickly), produces lists of numbers
anyway.
Why not strings containing the embedded binary data?
 And it would be, IMHO, absurd to have much bigger files than that
embedded with your executable in this manner.
BM complained that some files expressed as xxd-like output were causing problems with compilers.
I suggested using a string representation. While the generated text file
is not much smaller, it is seen by the compiler as one string
expression, instead of millions of small expressions. Or at least,
1/20th the number if you split the strings across lines.
It's a no-brainer. Why spend 10 times as long on processing such data?
On 12/06/2024 08:01, David Brown wrote:
On 12/06/2024 07:40, Bonita Montero wrote:You don't get what Baby X is all about.
Am 11.06.2024 um 18:15 schrieb Malcolm McLean:
These are Baby programs. But they use a cut down GUI. So they need
to get fonts and images into the program somehow. And so Baby X does
that by converting to 32 bit C arrays which can be compiled and
linked as normal. And for that, you need a tool. Writing a tiff file
decoder is not a trivial exercise.
I converted my code into sth. that produces a C-string as an output.
Printing that is still very fast, i.e. the files produced are written
with about 2.6GiB/s. But the problem is still that all compilers don't
parse large files but quit with an out of memory error. So having a
.obj output along with a small header file would be the best.
How big files are you talking about? In an earlier thread (which I
thought had beaten this topic to death), "xxd -i" include files were
fine to at least a few tens of megabytes with gcc. And it would be,
IMHO, absurd to have much bigger files than that embedded with your
executable in this manner. I can understand wanting some icons and a
few resource files in a PC executable, but if you have a lot of files
or big files then a single massive executable often does not make much
sense as the binary file.
If you /do/ want such a file, it is typically for making a portable
package that can be run directly without installing. But then you
don't mess around with inventing your own little pretend file systems,
or embedding the files manually, or using absurd ideas like XML text
strings.  You use standard, well-established solutions and tools such
as AppImage on Linux or self-extracting zip files on Windows.
These solutions will not work for the audience I am trying to target.
Baby X is clean, portable, and simple. As much as I can make it. And
it's meant to be easy for people who are just beginning programmers to use.
But the main focus now is help and documentation. The improved ls
command is now in the shell, and the next task is to improve the "help" command, at the same time as writing more docs. The two tasks naturally
go together, and the website is beginning to gel.
I also don't imagine that string literals would be much faster for compilation, at least for file sizes that I think make sense.
And I
have heard (it could be wrong) that MSVC has severe limits on the
size of string literals, though it is not a compiler I ever use
myself.
On Wed, 12 Jun 2024 15:46:44 +0200
David Brown <david.brown@hesbynett.no> wrote:
I also don't imagine that string literals would be much faster for
compilation, at least for file sizes that I think make sense.
Just shows how little do you know about internals of typical compiler.
Which, by itself, is o.k. What is not o.k. is that with your level of knowledge you have a nerve to argue vs bart that obviously knows a lot
more.
And I
have heard (it could be wrong) that MSVC has severe limits on the
size of string literals, though it is not a compiler I ever use
myself.
Citation, please..
On 12/06/2024 23:29, Michael S wrote:
On Wed, 12 Jun 2024 15:46:44 +0200
David Brown <david.brown@hesbynett.no> wrote:
I also don't imagine that string literals would be much faster for
compilation, at least for file sizes that I think make sense.
Just shows how little do you know about internals of typical compiler.
Which, by itself, is o.k. What is not o.k. is that with your level of
knowledge you have a nerve to argue vs bart that obviously knows a lot
more.
I know more than most C programmers about how certain C compilers work,
and what works well with them, and what is relevant for them - though I certainly don't claim to know everything. Obviously Bart knows vastly
more about how /his/ compiler works. He also tends to do testing with several small and odd C compilers, which can give interesting results
even though they are of little practical relevance for real-world C development work.
Testing a 1 MB file of random data, gcc -O2 took less than a second to compile it. One megabyte is about the biggest size I would think makes sense to embed directly in C code unless you are doing something very
niche - usually if you need that much data, you'd be better off with
separate files and standardised packaging systems like zip files,
installer setup.exe builds, or that kind of thing.
Using string literals, the compile time was shorter, but when you are
already below a second, it's all just irrelevant noise.
Each individual string is up to 2048 bytes, which can be concatenated to
a maximum of 65K in total.
I see other links giving different values, but I expect the MS ones to
be authoritative. It is possible that newer versions of their C
compiler have removed the limit, just as for their C++ compiler, but it
was missing from that webpage.
(And I noticed also someone saying that MSVC is 70x faster at using
string literals compared to lists of integers for array initialisation.)
Note that it is not necessary to use one giant string; you can chop it
up into smaller strings, say with one line's worth of values per string,
and still get most of the benefits. It's just a tiny bit more fiddly to generate the strings.
On 12/06/2024 23:29, Michael S wrote:
On Wed, 12 Jun 2024 15:46:44 +0200
David Brown <david.brown@hesbynett.no> wrote:
I also don't imagine that string literals would be much faster for
compilation, at least for file sizes that I think make sense.
Just shows how little do you know about internals of typical
compiler. Which, by itself, is o.k. What is not o.k. is that with
your level of knowledge you have a nerve to argue vs bart that
obviously knows a lot more.
I know more than most C programmers about how certain C compilers
work, and what works well with them, and what is relevant for them -
though I certainly don't claim to know everything. Obviously Bart
knows vastly more about how /his/ compiler works. He also tends to
do testing with several small and odd C compilers, which can give
interesting results even though they are of little practical
relevance for real-world C development work.
Testing a 1 MB file of random data, gcc -O2 took less than a second
to compile it.
One megabyte is about the biggest size I would think
makes sense to embed directly in C code unless you are doing
something very niche - usually if you need that much data, you'd be
better off with separate files and standardised packaging systems
like zip files, installer setup.exe builds, or that kind of thing.
Using string literals, the compile time was shorter, but when you are
already below a second, it's all just irrelevant noise.
For much bigger files, string literals are likely to be faster for compilation for gcc because the compiler does not track as much
information
(for use in diagnostic messages).
But it makes no
difference to real world development.
And I
have heard (it could be wrong) that MSVC has severe limits on the
size of string literals, though it is not a compiler I ever use
myself.
Citation, please..
<https://letmegooglethat.com/?q=msvc+string+literal+length+limit>
Actually, I think it was from Bart that I first heard that MSVC has limitations on its string literal lengths, but I could well be
misremembering that. I am confident, however, that it was here in
c.l.c., as MSVC is not a tool I have used myself.
<https://learn.microsoft.com/en-us/cpp/cpp/string-and-character-literals-cpp>
It seems that version 17.0 has removed the arbitrary limits, while
before that it was limited to 65K in their C++ compiler.
For the MSVC C compiler, I see this:
<https://learn.microsoft.com/en-us/cpp/c-language/maximum-string-length>
Each individual string is up to 2048 bytes, which can be concatenated
to a maximum of 65K in total.
I see other links giving different values, but I expect the MS ones
to be authoritative. It is possible that newer versions of their C
compiler have removed the limit, just as for their C++ compiler, but
it was missing from that webpage.
(And I noticed also someone saying that MSVC is 70x faster at using
string literals compared to lists of integers for array
initialisation.)
On 6/13/24 15:46, bart wrote:
Note that it is not necessary to use one giant string; you can chop it
up into smaller strings, say with one line's worth of values per
string, and still get most of the benefits. It's just a tiny bit more
fiddly to generate the strings.
  And what about the ending '\0' of all those small strings ?
Within my compiler, each single number takes a 64-byte record to
represent. So 1MB of data takes 64MB, while a 1MB string takes one
64-byte record plus the 1MB of the string data.
Then there are the various type analysis and other passes that have
to be done a million times rather then once. I'd imagine that
compilers like gcc do a lot more.
On Thu, 13 Jun 2024 13:53:54 +0200
David Brown <david.brown@hesbynett.no> wrote:
On 12/06/2024 23:29, Michael S wrote:
On Wed, 12 Jun 2024 15:46:44 +0200
David Brown <david.brown@hesbynett.no> wrote:
I also don't imagine that string literals would be much faster for
compilation, at least for file sizes that I think make sense.
Just shows how little do you know about internals of typical
compiler. Which, by itself, is o.k. What is not o.k. is that with
your level of knowledge you have a nerve to argue vs bart that
obviously knows a lot more.
I know more than most C programmers about how certain C compilers
work, and what works well with them, and what is relevant for them -
though I certainly don't claim to know everything. Obviously Bart
knows vastly more about how /his/ compiler works. He also tends to
do testing with several small and odd C compilers, which can give
interesting results even though they are of little practical
relevance for real-world C development work.
Since he do compilers himself, he has much better feeling [that you
or me] of what is hard and what is easy, what is small and what is big,
what is fast and what is slow. That applies to all compilers except
those that are very unusual. "Major" compiler are not unusual at all.
Testing a 1 MB file of random data, gcc -O2 took less than a second
to compile it.
Somewhat more than a second on less modern hardware. Enough for me to
feel that compilation is not instant.
But 1 MB is just an arbitrary number. For 20 MB everybody would feel
the difference. And for 50 MB few people would not want it to be much
faster.
One megabyte is about the biggest size I would think
makes sense to embed directly in C code unless you are doing
something very niche - usually if you need that much data, you'd be
better off with separate files and standardised packaging systems
like zip files, installer setup.exe builds, or that kind of thing.
Using string literals, the compile time was shorter, but when you are
already below a second, it's all just irrelevant noise.
For much bigger files, string literals are likely to be faster for
compilation for gcc because the compiler does not track as much
information
And that is sort of the thing that bart knows immediately. Unlike you
and me.
And I
have heard (it could be wrong) that MSVC has severe limits on the
size of string literals, though it is not a compiler I ever use
myself.
For the MSVC C compiler, I see this:
<https://learn.microsoft.com/en-us/cpp/c-language/maximum-string-length>
Each individual string is up to 2048 bytes, which can be concatenated
to a maximum of 65K in total.
I see other links giving different values, but I expect the MS ones
to be authoritative. It is possible that newer versions of their C
compiler have removed the limit, just as for their C++ compiler, but
it was missing from that webpage.
(And I noticed also someone saying that MSVC is 70x faster at using
string literals compared to lists of integers for array
initialisation.)
I didn't know it, thanks.
It means that string method can't be used universally.
Still, for C (as opposed to C++), limitation of compiler can be tricked around by declaring container as a struct. E.g. for array of length
1234567
struct {
char bulk[123][10000];
char tail[4567];
} bar = {
{
"init0-to-99999" ,
"init10000-to-199999" ,
....
},
"init123400-to1234566"
};
For that I'd expecte compilation speed almost as fast as of one string.
On 13/06/2024 16:43, Michael S wrote:
Somewhat more than a second on less modern hardware. Enough for me to
feel that compilation is not instant.
But 1 MB is just an arbitrary number. For 20 MB everybody would feel
the difference. And for 50 MB few people would not want it to be much
faster.
But what would be the point of trying to embed such files in the first place? There are much better ways of packing large files.
 You can
always increase sizes for things until you get problems or annoying slowdowns, but that does not mean that will happen in practical situations.
And even if you /did/ want to embed a 20 MB file, and even if that took
20 seconds, so what? Unless you have a masochistic build setup, such as refusing to use "make" or insisting that everything goes in one C file
that is re-compiled all the time, that 20 second compile is a one-off
time cost on the rare occasion when you change the big binary file.
Now, I am quite happy to agree that faster is better, all other things
being equal. And convenience and simplicity is better. Once the
compilers I use support #embed, if I need to embed a file and I don't
need anything more than an array initialisation, I'll use #embed. Until then, 5 seconds writing an "xxd -i" line in a makefile and a 20 second compile (if it took that long) beats 5 minutes writing a Python script
to generate string literals even if the compile is now 2 seconds.
Until
then, 5 seconds writing an "xxd -i" line in a makefile and a 20 second compile (if it took that long) beats 5 minutes writing a Python script
to generate string literals even if the compile is now 2 seconds.
Unless you have a masochistic build setup, such as
refusing to use "make" or insisting that everything goes in one C file
that is re-compiled all the time,
On 14/06/2024 17:43, David Brown wrote:
On 13/06/2024 16:43, Michael S wrote:
Somewhat more than a second on less modern hardware. Enough for me to
feel that compilation is not instant.
But 1 MB is just an arbitrary number. For 20 MB everybody would feel
the difference. And for 50 MB few people would not want it to be much
faster.
But what would be the point of trying to embed such files in the first
place? There are much better ways of packing large files.
I remember complaining that some tool installations were bloated at
100MB, 500MB, 1000MB or beyond, and your attitude was So what, since
there is now almost unlimited storage.
But now of course, it's Why would someone ever want to do X with such a
large file! Suddenly large files are undesirable when it suits you.
 You can always increase sizes for things until you get problems or
annoying slowdowns, but that does not mean that will happen in
practical situations.
And even if you /did/ want to embed a 20 MB file, and even if that
took 20 seconds, so what? Unless you have a masochistic build setup,
such as refusing to use "make" or insisting that everything goes in
one C file that is re-compiled all the time, that 20 second compile is
a one-off time cost on the rare occasion when you change the big
binary file.
Now, I am quite happy to agree that faster is better, all other things
being equal. And convenience and simplicity is better. Once the
compilers I use support #embed, if I need to embed a file and I don't
need anything more than an array initialisation, I'll use #embed.
Until then, 5 seconds writing an "xxd -i" line in a makefile and a 20
second compile (if it took that long) beats 5 minutes writing a Python
script to generate string literals even if the compile is now 2 seconds.
That's a really bad attitude. It partly explains why such things as
#embed take so long to get added.
I've heard lots of horror stories elsewhere about projects taking
minutes, tens of minutes or even hours to build.
How much of that is due to attitudes like yours? You've managed to find
ways of working around speed problems, by throwing hardware resources at
it (fast processors, loads of memory, multiple cores, SSD, RAM-disk), or using ingenuity in *avoiding* having to compile stuff as much as
possible. Or maybe the programs you build aren't that big.
On Thu, 13 Jun 2024 13:53:54 +0200...
David Brown <david.brown@hesbynett.no> wrote:
I know more than most C programmers about how certain C compilers
work, and what works well with them, and what is relevant for them -
though I certainly don't claim to know everything. Obviously Bart
knows vastly more about how /his/ compiler works. He also tends to
do testing with several small and odd C compilers, which can give
interesting results even though they are of little practical
relevance for real-world C development work.
Since he do compilers himself, he has much better feeling [that you
or me] of what is hard and what is easy, what is small and what is big,
what is fast and what is slow. That applies to all compilers except
those that are very unusual. "Major" compiler are not unusual at all.
The problem is that Bart's compiler is VERY unusual. It's customized for
his use, and he has lots of quirks in the way he thinks compilers should work, which are very different from those of most other programmers. In particular, compilation speed is very important to him, while execution
speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
On 2024-06-17, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
The problem is that Bart's compiler is VERY unusual. It's
customized for his use, and he has lots of quirks in the way he
thinks compilers should work, which are very different from those
of most other programmers. In particular, compilation speed is very important to him, while execution speed is almost completely
unimportant, which is pretty much the opposite of the way most
programmers prioritize those things.
Most programmers use Javascript and Python, which follow Bart's
priorities. Fast, invisible compilation to some kind of byte code
(plus possibly later JIT), slow execution time.
On 6/13/24 10:43, Michael S wrote:
On Thu, 13 Jun 2024 13:53:54 +0200...
David Brown <david.brown@hesbynett.no> wrote:
I know more than most C programmers about how certain C compilers
work, and what works well with them, and what is relevant for them -
though I certainly don't claim to know everything. Obviously Bart
knows vastly more about how /his/ compiler works. He also tends to
do testing with several small and odd C compilers, which can give
interesting results even though they are of little practical
relevance for real-world C development work.
Since he do compilers himself, he has much better feeling [that you
or me] of what is hard and what is easy, what is small and what is big,
what is fast and what is slow. That applies to all compilers except
those that are very unusual. "Major" compiler are not unusual at all.
The problem is that Bart's compiler is VERY unusual. It's customized for
his use, and he has lots of quirks in the way he thinks compilers should work, which are very different from those of most other programmers.
In
particular, compilation speed is very important to him, while execution
speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
On 2024-06-17, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
The problem is that Bart's compiler is VERY unusual. It's customized for
his use, and he has lots of quirks in the way he thinks compilers should
work, which are very different from those of most other programmers. In
particular, compilation speed is very important to him, while execution
speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
Most programmers use Javascript and Python, which follow Bart's
priorities. Fast, invisible compilation to some kind of byte code (plus possibly later JIT), slow execution time.
On 17/06/2024 07:22, James Kuyper wrote:
On 6/13/24 10:43, Michael S wrote:
On Thu, 13 Jun 2024 13:53:54 +0200...
David Brown <david.brown@hesbynett.no> wrote:
I know more than most C programmers about how certain C compilers
work, and what works well with them, and what is relevant for them -
though I certainly don't claim to know everything. Obviously Bart
knows vastly more about how /his/ compiler works. He also tends to
do testing with several small and odd C compilers, which can give
interesting results even though they are of little practical
relevance for real-world C development work.
Since he do compilers himself, he has much better feeling [that you
or me] of what is hard and what is easy, what is small and what is big,
what is fast and what is slow. That applies to all compilers except
those that are very unusual. "Major" compiler are not unusual at all.
The problem is that Bart's compiler is VERY unusual. It's customized for
his use, and he has lots of quirks in the way he thinks compilers should
work, which are very different from those of most other programmers.
In
particular, compilation speed is very important to him, while execution
speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
Compilation speed is important to everyone. That's why so many tricks
are used to get around the lack of speed in a big compiler, or so many
extra resources are thrown at the problem.
Runtime performance is important too, but at this level of language, the difference between optimised and unoptimised code is narrow. Unoptimised
may be between 1x and 2x slower, typically.
Perhaps slower on benchmarks, or code written in C++ style that
generates lots of redundances that relies on optimisation to make it fast.
But, during developement, you probably wouldn't use optimisation anyway.
In that case, you're still suffering slow build times with a big
compiler, but you don't get any faster code at the end of it.
I sometimes suggest to people to use Tiny C most of the time, and run
gcc from time to time for extra analysis and extra checks, and use
gcc-O3 for production builds.
(I have also suggested that gcc should incorporate a -O-1 option that
runs a secretly bundled of Tiny C.)
On 17/06/2024 07:22, James Kuyper wrote:
On 6/13/24 10:43, Michael S wrote:Yes, but that's probably what you want.
On Thu, 13 Jun 2024 13:53:54 +0200...
David Brown <david.brown@hesbynett.no> wrote:
I know more than most C programmers about how certain C compilers
work, and what works well with them, and what is relevant for them -
though I certainly don't claim to know everything. Obviously Bart
knows vastly more about how /his/ compiler works. He also tends to
do testing with several small and odd C compilers, which can give
interesting results even though they are of little practical
relevance for real-world C development work.
Since he do compilers himself, he has much better feeling [that you
or me] of what is hard and what is easy, what is small and what is big,
what is fast and what is slow. That applies to all compilers except
those that are very unusual. "Major" compiler are not unusual at all.
The problem is that Bart's compiler is VERY unusual. It's customized for
his use, and he has lots of quirks in the way he thinks compilers should
work, which are very different from those of most other programmers. In
particular, compilation speed is very important to him, while execution
speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
As a one man band, bart can't
bear Aple and Microsoft in priiducing a compiler which creates highly optimised code that executes quickly. And that's what the vast majority
of customers want.
But say that 0.1% of customers are more interested in compilation speed.
Now, Apple and Microsoft might not even bother catering to, what is to
them, just a tiny market and a disraction for the development team. So
bart can plausibly produce a compiler which does compile code correctly,
and much faster than the big boys. And there are about 28 million pepole
in the world who derive thetr living as computer programmers. 0.1% of
that is 28,000, Charge 10 dollars each, and that's a nice little
business for one person.
On 17/06/2024 14:43, David Brown wrote:
On 17/06/2024 12:30, bart wrote:I never do.
On 17/06/2024 07:22, James Kuyper wrote:
On 6/13/24 10:43, Michael S wrote:
On Thu, 13 Jun 2024 13:53:54 +0200...
David Brown <david.brown@hesbynett.no> wrote:
The problem is that Bart's compiler is VERY unusual. It's customizedI know more than most C programmers about how certain C compilers
work, and what works well with them, and what is relevant for them - >>>>>> though I certainly don't claim to know everything. Obviously Bart
knows vastly more about how /his/ compiler works. He also tends to >>>>>> do testing with several small and odd C compilers, which can give
interesting results even though they are of little practical
relevance for real-world C development work.
Since he do compilers himself, he has much better feeling [that you
or me] of what is hard and what is easy, what is small and what is
big,
what is fast and what is slow. That applies to all compilers except
those that are very unusual. "Major" compiler are not unusual at all. >>>>
for
his use, and he has lots of quirks in the way he thinks compilers
should
work, which are very different from those of most other programmers.
In
particular, compilation speed is very important to him, while execution >>>> speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
Compilation speed is important to everyone. That's why so many tricks
are used to get around the lack of speed in a big compiler, or so
many extra resources are thrown at the problem.
What "tricks" ?
Runtime performance is important too, but at this level of language,
the difference between optimised and unoptimised code is narrow.
Unoptimised may be between 1x and 2x slower, typically.
That depends on the language, type of code, and target platform.
Typical C code on an x86_64 platform might be two or three times
slower when using a poorly optimising compiler. After all, the
designers of x86 cpus put a great deal of effort into making shitty
code run fast. For high-performance code written with care and
requiring fast results, the performance difference will be bigger.
For C++, especially code that makes good use of abstractions, the
difference can be very much bigger. For C code on an embedded ARM
device or other microcontroller, it's not unusual to see a 5x speed
improvement on optimised code.
Speed is not the only good reason for picking C as the language for a
task, but it is often a relevant factor. And if it is a factor, then
you will usually prefer faster speeds.
Perhaps slower on benchmarks, or code written in C++ style that
generates lots of redundances that relies on optimisation to make it
fast.
But, during developement, you probably wouldn't use optimisation anyway. >>>
I virtually always have optimisation enabled during development. I
might, when trying to chase down a specific bug, reduce some specific
optimisations, but I have never seen the point of crippling a
development tool when doing development work - it makes no sense at all.
Until I had to give up work, I was making real time tools for artists.
And if it didn't work in under just noticeable time on the debug build,
it wouldn't be working in under just noticeable time on the release
build, you could be pretty sure. So I never turned the release build on,
but of course the downstream deployment team built it as release for
delivery to customers. And that might mean that they could do 2000 paths instead of 1000 before the tool slowed to the point that it became
unusable. So not a game changer. But not something to deprive a customer
of either.
On 17/06/2024 12:30, bart wrote:
On 17/06/2024 07:22, James Kuyper wrote:
On 6/13/24 10:43, Michael S wrote:
On Thu, 13 Jun 2024 13:53:54 +0200...
David Brown <david.brown@hesbynett.no> wrote:
I know more than most C programmers about how certain C compilers
work, and what works well with them, and what is relevant for them - >>>>> though I certainly don't claim to know everything. Obviously Bart
knows vastly more about how /his/ compiler works. He also tends to
do testing with several small and odd C compilers, which can give
interesting results even though they are of little practical
relevance for real-world C development work.
Since he do compilers himself, he has much better feeling [that you
or me] of what is hard and what is easy, what is small and what is big, >>>> what is fast and what is slow. That applies to all compilers except
those that are very unusual. "Major" compiler are not unusual at all.
The problem is that Bart's compiler is VERY unusual. It's customized for >>> his use, and he has lots of quirks in the way he thinks compilers should >>> work, which are very different from those of most other programmers.
In
particular, compilation speed is very important to him, while execution
speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
Compilation speed is important to everyone. That's why so many tricks
are used to get around the lack of speed in a big compiler, or so many
extra resources are thrown at the problem.
What "tricks" ?
Runtime performance is important too, but at this level of language,
the difference between optimised and unoptimised code is narrow.
Unoptimised may be between 1x and 2x slower, typically.
That depends on the language, type of code, and target platform. Typical
C code on an x86_64 platform might be two or three times slower when
using a poorly optimising compiler. After all, the designers of x86
cpus put a great deal of effort into making shitty code run fast. For high-performance code written with care and requiring fast results, the performance difference will be bigger. For C++, especially code that
makes good use of abstractions, the difference can be very much bigger.
For C code on an embedded ARM device or other microcontroller, it's not unusual to see a 5x speed improvement on optimised code.
Speed is not the only good reason for picking C as the language for a
task, but it is often a relevant factor. And if it is a factor, then
you will usually prefer faster speeds.
Perhaps slower on benchmarks, or code written in C++ style that
generates lots of redundances that relies on optimisation to make it
fast.
But, during developement, you probably wouldn't use optimisation anyway.
I virtually always have optimisation enabled during development. I
might, when trying to chase down a specific bug, reduce some specific optimisations, but I have never seen the point of crippling a
development tool when doing development work - it makes no sense at all.
In that case, you're still suffering slow build times with a big
compiler, but you don't get any faster code at the end of it.
I sometimes suggest to people to use Tiny C most of the time, and run
gcc from time to time for extra analysis and extra checks, and use
gcc-O3 for production builds.
I cannot imagine any situation where I would think that might be a good
idea.
But then, I see development tools as tools to help my work as a
developer, while you seem to consider tools (other than your own) as
objects of hatred to be avoided whenever possible or dismissed as
"tricks". I don't expect we will ever agree there.
On 17/06/2024 17:21, David Brown wrote:
On 17/06/2024 17:48, Malcolm McLean wrote:I drive C in first gear when I'm developing, which means that the car is given instructions to go to the right place and obey all, the rules of
Using C without optimisation is like driving a car but refusing to go
out of first gear. You would probably have been better off with a
bicycle or driving a tank, according to the task at hand.
the road.
But it never gets out of frst gear when I'm driving it.
However because of the nature of what we do, which is interactivce programming mostly, usually "just noticeable" time is sufficient. It's a
bit like driving in London - a top of the range sports car is no better
than a beat up old mini, they travel at the same speed because of all
the interactions.
They I had it over to the deployment team, and they take the restraints
off, and allow it to go up to top gear, and it is compiled with full optimisation.
And I don't actually have a computer with one of the most
important hardware targets, but it's all written in C++, a bit in C, and
none in assembler. So I can't profile it, and I have to rely on insight
into where the inner loop will be, and how to avoid expensive operations
in the inner loop.
And hopefully those subroutines will be called for many years to come,
or hardware as yet un-designed.
With Baby X, I did have severe problems with the rendering speed on an
old Windows machine. But I haven;t noticed them now its runnng on the
Apple Mac. However as the name suggests, Baby X was first designed for X
lib. I only added Windows support later, and all the rgba buffers were
in the wrong format. But faster processors cover a multitude of sins, if
you keep things lean.
Using C without optimisation is like driving a car but refusing to go
out of first gear. You would probably have been better off with a
bicycle or driving a tank, according to the task at hand.
Having a distinction in optimisation between "debug" and "release"
builds is simply /wrong/. Release what you have debugged, debug what
you intend to release.
On 17/06/2024 20:29, David Brown wrote:
On 17/06/2024 21:17, Malcolm McLean wrote:You know what hardware your code will run on. I don't.
On 17/06/2024 17:21, David Brown wrote:
On 17/06/2024 17:48, Malcolm McLean wrote:I drive C in first gear when I'm developing, which means that the car
Using C without optimisation is like driving a car but refusing to
go out of first gear. You would probably have been better off with
a bicycle or driving a tank, according to the task at hand.
is given instructions to go to the right place and obey all, the
rules of the road.
I do my C development with optimisations enabled, which means that the
C compiler will obey all the rules and requirements of C.
Optimisations don't change the meaning of correct code - they only
have an effect on the results of your code if you have written
incorrect code. I don't know about you, but my aim in development is
to write /correct/ code. If disabling optimisations helped in some
way, it would be due to bugs and luck.
But it never gets out of frst gear when I'm driving it. However
because of the nature of what we do, which is interactivce
programming mostly, usually "just noticeable" time is sufficient.
It's a bit like driving in London - a top of the range sports car is
no better than a beat up old mini, they travel at the same speed
because of all the interactions.
If I am writing PC code where the timing is determined by user
interaction, I would not be writing in C - it is almost certainly a
poor choice of language for the task.
They I had it over to the deployment team, and they take the
restraints off, and allow it to go up to top gear, and it is compiled
with full optimisation.
That is insane development practice, if I understand you correctly.
For some kinds of development work, it can make sense to have one
person (or team) make prototypes or proofs-of-concept, and then have
another person (or team) use that as a guide, specification and test
comparison when writing a fast implementation for the real product.
But the prototype should be in a high-level language, written in the
clearest and simplest manner - not crappy code in a low-level language
that works by luck when it is not optimised!
And I don't actually have a computer with one of the most important
hardware targets, but it's all written in C++, a bit in C, and none
in assembler. So I can't profile it, and I have to rely on insight
into where the inner loop will be, and how to avoid expensive
operations in the inner loop.
If you are writing C++ and are not happy about using optimisation, you
are in the wrong job.
On 17/06/2024 17:21, David Brown wrote:
Using C without optimisation is like driving a car but refusing to go
out of first gear. You would probably have been better off with a
bicycle or driving a tank, according to the task at hand.
Which bit is the car: the compiler, or the program that it produces?
When I am developing, it is the compiler that is used more often. Or, if
I spend a lot of time on a particular build of an application, the speed
at which it runs is rarely critical, since during most testing, the
scale of the tasks is small.
So if the compiler is the car, then one like tcc goes at 60mph while gcc
goes at walking pace.
On 2024-06-17, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
The problem is that Bart's compiler is VERY unusual. It's customized for
his use, and he has lots of quirks in the way he thinks compilers should
work, which are very different from those of most other programmers. In
particular, compilation speed is very important to him, while execution
speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
Most programmers use Javascript and Python, which follow Bart's
priorities. Fast, invisible compilation to some kind of byte code (plus possibly later JIT), slow execution time.
On 17/06/2024 15:09, Malcolm McLean wrote:...
On 17/06/2024 07:22, James Kuyper wrote:
The problem is that Bart's compiler is VERY unusual. It's customized for >>> his use, and he has lots of quirks in the way he thinks compilers should >>> work, which are very different from those of most other programmers. InYes, but that's probably what you want.
particular, compilation speed is very important to him, while execution
speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
Who is "you" here? Possibly "you" is Bart, but it is certainly not /me/.
I use Python rather than C because for
PC code, that can often involve files, text manipulation, networking,
and various data structures, the Python code is at least an order of magnitude shorter and faster to write. When I see the amount of
faffing around in order to read and parse a file consisting of a list
of integers, I find it amazing that anyone would actively choose C
for the task (unless it is for the fun of it).
On 6/17/24 12:21, David Brown wrote:
...
Having a distinction in optimisation between "debug" and "release"
builds is simply /wrong/. Release what you have debugged, debug what
you intend to release.
I fully agree that you should debug what you intend to release; but I
can't agree that it always makes sense to release what you've debugged.
There are ways to debug code that make it horribly inefficient - they
are also good ways to uncover certain kinds of bugs.
There should be a
debug mode where you enable that inefficient code, and track down and
remove any bugs that you find. Then you go to release mode, and test it
as thoroughly as possible with the code as it is intended to be
released, which is never as much can be possible in debug mode. Do not release until the final version of the code has passed both sets of
tests. If release testing uncovers a bug that requires a code change,
that means that debug testing also needs to be redone.
On 17/06/2024 14:43, David Brown wrote:
On 17/06/2024 12:30, bart wrote:
On 17/06/2024 07:22, James Kuyper wrote:
On 6/13/24 10:43, Michael S wrote:
On Thu, 13 Jun 2024 13:53:54 +0200...
David Brown <david.brown@hesbynett.no> wrote:
If you don't need optimised code right now, why would you invoke gcc
rather than tcc? It's a no-brainer.
On Mon, 17 Jun 2024 15:23:55 +0200
David Brown <david.brown@hesbynett.no> wrote:
I use Python rather than C because for
PC code, that can often involve files, text manipulation, networking,
and various data structures, the Python code is at least an order of
magnitude shorter and faster to write. When I see the amount of
faffing around in order to read and parse a file consisting of a list
of integers, I find it amazing that anyone would actively choose C
for the task (unless it is for the fun of it).
The faffing (what does it mean, BTW ?) is caused by unrealistic
requirements. More specifically, by requirements of (A) to support
arbitrary line length (B) to process file line by line. Drop just one
of those requirements and everything become quite simple.
For task like that Python could indeed be several times shorter, but
only if you wrote your python script exclusively for yourself, cutting
all corners, like not providing short help for user, not testing that
input format matches expectations and most importantly not reporting
input format problems in potentially useful manner.
OTOH, if we write our utility in more "anal" manner, as we should if
we expect it to be used by other people or by ourselves long time after
it was written (in my age, couple of months is long enough and I am not
that much older than you) then code size difference between python and
C variants will be much smaller, probably factor of 2 or so.
W.r.t. faster to code, it very strongly depends on familiarity.
You didn't do that sort of tasks in 'C' since your school days, right?
Or ever? And you are doing them in Python quite regularly? Then that is
much bigger reason for the difference than the language itself.
Now, for more complicated tasks Python, as the language, and even more importantly, Python as a massive set of useful libraries could have
very big productivity advantage over 'C'. But it does not apply to very simple thing like reading numbers from text file.
In the real world, I wrote utility akin to that less than two years ago.
It converted big matrices from space delimited text to Matlab v4 .mat
format. Why did I do it? Because while both Matlab and Gnu Octave are
capable of reading text files like those, but they are quite slow doing
so. With huge files that I was using at the moment, it became
uncomfortable.
I wrote it in 'C' (or was it C-style C++ ? I don't remember) mostly
because I knew how to produce v4 .mat files in C. If I were doing it in Python, I'd have to learn how to do it in Python and at the end it
would have taken me more time rather than less. I didn't even came to
the point of evaluating whether speed of python's functions for parsing
text was sufficient for my needs.
On 18/06/2024 10:56, Michael S wrote:
On Mon, 17 Jun 2024 15:23:55 +0200
David Brown <david.brown@hesbynett.no> wrote:
I use Python rather than C because for
PC code, that can often involve files, text manipulation, networking,
and various data structures, the Python code is at least an order of
magnitude shorter and faster to write. When I see the amount of
faffing around in order to read and parse a file consisting of a list
of integers, I find it amazing that anyone would actively choose C
for the task (unless it is for the fun of it).
The faffing (what does it mean, BTW ?) is caused by unrealistic
requirements. More specifically, by requirements of (A) to support
arbitrary line length (B) to process file line by line. Drop just one
of those requirements and everything become quite simple.
"Faffing around" or "faffing about" means messing around doing
unimportant or unnecessary things instead of useful things. In this
case, it means writing lots of code for handling memory management to
read a file instead of using a higher-level language and just reading
the file.
Yes, dropping requirements might make the task easier in C. But you
still don't get close to being as easy as it is in a higher level
language. (That does not have to be Python - I simply use that as an example that I am familiar with, and many others here will also have at
least some experience of it.)
For task like that Python could indeed be several times shorter, but
only if you wrote your python script exclusively for yourself, cutting
all corners, like not providing short help for user, not testing that
input format matches expectations and most importantly not reporting
input format problems in potentially useful manner.
No, even if that were part of the specifications, it would still be far easier in Python. The brief Python samples I have posted don't cover
such user help, options, error checking, etc., but that's because they
are brief samples.
OTOH, if we write our utility in more "anal" manner, as we should if
we expect it to be used by other people or by ourselves long time after
it was written (in my age, couple of months is long enough and I am not
that much older than you) then code size difference between python and
C variants will be much smaller, probably factor of 2 or so.
Unless half the code is a text string for a help page, I'd expect a
bigger factor. And I'd expect the development time difference to be an
even bigger factor - with Python you avoid a number of issues that are
easy to get wrong in C (such as memory management). Of course that
would require a reasonable familiarity of both languages for a fair comparison.
C and Python are both great languages, with their pros and cons and
different areas where they shine. There can be good reasons for writing
a program like this in C rather than Python, but C is often used without
good technical reasons. To me, it is important to know a number of
tools and pick the best one for any given job.
W.r.t. faster to code, it very strongly depends on familiarity.
You didn't do that sort of tasks in 'C' since your school days, right?
Or ever? And you are doing them in Python quite regularly? Then that is
much bigger reason for the difference than the language itself.
Sure - familiarity with a particular tool is a big reason for choosing it.
Now, for more complicated tasks Python, as the language, and even more
importantly, Python as a massive set of useful libraries could have
very big productivity advantage over 'C'. But it does not apply to very
simple thing like reading numbers from text file.
IMHO, it does. I have slightly lost track of which programs were being discussed in which thread, but the Python code for the task is a small fraction of the size of the C code. I agree that if you want to add
help messages and nicer error messages, the difference will go down.
Here is a simple task - take a file name as an command-line argument,
then read all white-space (space, tab, newlines, mixtures) separated integers. Add them up and print the count, sum, and average (as an integer). Give a brief usage message if the file name is missing, and a brief error if there is something that is not an integer. This should
be a task that you see as very simple in C.
#!/usr/bin/python3
import sys
if len(sys.argv) < 2 :
    print("Usage: sums.py <input-file>")
    sys.exit(1)
data = list(map(int, open(sys.argv[1], "r").read().split()))
n = len(data)
s = sum(data)
print("Count: %i, sum %i, average %i" % (n, s, s // n))
If you don't need optimised code right now, why would you invoke gcc
rather than tcc? It's a no-brainer.
On 17/06/2024 21:24, bart wrote:
On 17/06/2024 14:43, David Brown wrote:
On 17/06/2024 12:30, bart wrote:
On 17/06/2024 07:22, James Kuyper wrote:
On 6/13/24 10:43, Michael S wrote:
On Thu, 13 Jun 2024 13:53:54 +0200...
David Brown <david.brown@hesbynett.no> wrote:
If you don't need optimised code right now, why would you invoke gcc
rather than tcc? It's a no-brainer.
You might use tcc if you have no brain. People who do C development seriously don't use the compiler just to generate an exe file. gcc is a development tool, not just a compiler. (As is clang, and MSVC.) If you think compilation speed of a subset of C is all that matters, you are
not doing C development.
On 17/06/2024 21:24, bart wrote:
...
If you don't need optimised code right now, why would you invoke gcc
rather than tcc? It's a no-brainer.
On virtually every occasion when I've heard someone claim that a given decision is a no-brainer, I would generally make a different decision if
I actually applied my brain to the issue. This is no exception.
On 18/06/2024 14:39, James Kuyper wrote:
On 17/06/2024 21:24, bart wrote:
...
If you don't need optimised code right now, why would you invoke gcc
rather than tcc? It's a no-brainer.
On virtually every occasion when I've heard someone claim that a given
decision is a no-brainer, I would generally make a different decision if
I actually applied my brain to the issue. This is no exception.
So your brain would tell you to choose a tool which takes at least 10
times as long to do the same task?
Of course if you don't know Python, it will be slower to write it in
Python!
And here's a simple task for you. Our filesystem uses a new technology
and is a bit dicey. Occasionally you will get a read error. Can you
modify the python to print out that a read error has occurred?
On 18/06/2024 13:36, David Brown wrote:
On 18/06/2024 10:56, Michael S wrote:
On Mon, 17 Jun 2024 15:23:55 +0200
David Brown <david.brown@hesbynett.no> wrote:
I use Python rather than C because for
PC code, that can often involve files, text manipulation, networking,
and various data structures, the Python code is at least an order of
magnitude shorter and faster to write. When I see the amount of
faffing around in order to read and parse a file consisting of a list
of integers, I find it amazing that anyone would actively choose C
for the task (unless it is for the fun of it).
The faffing (what does it mean, BTW ?) is caused by unrealistic
requirements. More specifically, by requirements of (A) to support
arbitrary line length (B) to process file line by line. Drop just one
of those requirements and everything become quite simple.
"Faffing around" or "faffing about" means messing around doing
unimportant or unnecessary things instead of useful things. In this
case, it means writing lots of code for handling memory management to
read a file instead of using a higher-level language and just reading
the file.
Yes, dropping requirements might make the task easier in C. But you
still don't get close to being as easy as it is in a higher level
language. (That does not have to be Python - I simply use that as an
example that I am familiar with, and many others here will also have
at least some experience of it.)
For task like that Python could indeed be several times shorter, but
only if you wrote your python script exclusively for yourself, cutting
all corners, like not providing short help for user, not testing that
input format matches expectations and most importantly not reporting
input format problems in potentially useful manner.
No, even if that were part of the specifications, it would still be
far easier in Python. The brief Python samples I have posted don't
cover such user help, options, error checking, etc., but that's
because they are brief samples.
OTOH, if we write our utility in more "anal" manner, as we should if
we expect it to be used by other people or by ourselves long time after
it was written (in my age, couple of months is long enough and I am not
that much older than you) then code size difference between python and
C variants will be much smaller, probably factor of 2 or so.
Unless half the code is a text string for a help page, I'd expect a
bigger factor. And I'd expect the development time difference to be
an even bigger factor - with Python you avoid a number of issues that
are easy to get wrong in C (such as memory management). Of course
that would require a reasonable familiarity of both languages for a
fair comparison.
C and Python are both great languages, with their pros and cons and
different areas where they shine. There can be good reasons for
writing a program like this in C rather than Python, but C is often
used without good technical reasons. To me, it is important to know a
number of tools and pick the best one for any given job.
W.r.t. faster to code, it very strongly depends on familiarity.
You didn't do that sort of tasks in 'C' since your school days, right?
Or ever? And you are doing them in Python quite regularly? Then that is
much bigger reason for the difference than the language itself.
Sure - familiarity with a particular tool is a big reason for choosing
it.
Now, for more complicated tasks Python, as the language, and even more
importantly, Python as a massive set of useful libraries could have
very big productivity advantage over 'C'. But it does not apply to very
simple thing like reading numbers from text file.
IMHO, it does. I have slightly lost track of which programs were
being discussed in which thread, but the Python code for the task is a
small fraction of the size of the C code. I agree that if you want to
add help messages and nicer error messages, the difference will go down.
Here is a simple task - take a file name as an command-line argument,
then read all white-space (space, tab, newlines, mixtures) separated
integers. Add them up and print the count, sum, and average (as an
integer). Give a brief usage message if the file name is missing, and
a brief error if there is something that is not an integer. This
should be a task that you see as very simple in C.
#!/usr/bin/python3
import sys
if len(sys.argv) < 2 :
     print("Usage: sums.py <input-file>")
     sys.exit(1)
data = list(map(int, open(sys.argv[1], "r").read().split()))
n = len(data)
s = sum(data)
print("Count: %i, sum %i, average %i" % (n, s, s // n))
A rather artificial task that you have to chosen so that it can be done
as a Python one-liner, for the main body.
Some characteristics of how it is done are that the whole file is read
into memory as effectively a single string, and all the numbers are
collated into an in-memory array before it is processed.
Numbers are also conveniently separated by white-space (no commas!), so
that .split can be used.
You are using features from Python that allow arbitrary large integers
that also avoid any overflow on that sum.
A C version wouldn't have all those built-ins to draw on (presumably you expect the starting point to be 'int main(int n ,char** args){}'; using existing libraries is not allowed).
Some would write it so that the file is processed serially and doesn't
have to occupy memory, or needed to deal with files that might fill up memory.
They might also try and avoid building a large data[] array that may
need to grow in size unless the bounds are determined in addvance.
The C version would be doing it in a different mannner, and likely to be
more efficient.
I haven't tried it directly in C (I don't have a C 'readfile's to hand);
I tried it in my language on a 100MB test input of 15M random numbers
ranging up to one million.
With a more arbitrary input format, this would be the kind of job that a compiler's lexer does. But nobody seriously writes lexers in Python.
On 18/06/2024 15:48, bart wrote:
I haven't tried it directly in C (I don't have a C 'readfile's to
hand); I tried it in my language on a 100MB test input of 15M random
numbers ranging up to one million.
No one is interested in that - that was not part of the task.
With a more arbitrary input format, this would be the kind of job that
a compiler's lexer does. But nobody seriously writes lexers in Python.
Yes, people do. (Look up the PLY project, for example.) Nobody
seriously writes lexers in C these days. They use Python or another
high level language during development, prototyping and experimentation,
and if the language takes off as a realistic general-purpose language,
they either write the lexer and the rest of the tools in the new
language itself, or they use C++.
On 18/06/2024 17:11, David Brown wrote:
On 18/06/2024 15:48, bart wrote:
I haven't tried it directly in C (I don't have a C 'readfile's to
hand); I tried it in my language on a 100MB test input of 15M random
numbers ranging up to one million.
No one is interested in that - that was not part of the task.
You're arguing in favour of a high level scripting language for task
rather than a lower level one which you claim involves a lot of
'faffing' around.
I tried it using mine (C would have taken 10 minutes longer), and found
it wasn't actually that hard, especially if you have some ready-made
routines lying around.
Plus it was a magnitude faster. Plus I showed how it could be run
without a discrete build step just like Python (Tcc has that feature for
C).
So for this example, there wasn't a lot in it, while the low-level could
was shown to be faster without trying too hard.
For a throwaway program that is only run once you probably would use the nearest scripting language; its extra runtime (5 seconds for my example)
is shorter than the next extra coding time.
But that's not why you might use C.
With a more arbitrary input format, this would be the kind of job
that a compiler's lexer does. But nobody seriously writes lexers in
Python.
Yes, people do. (Look up the PLY project, for example.) Nobody
seriously writes lexers in C these days. They use Python or another
high level language during development, prototyping and
experimentation, and if the language takes off as a realistic
general-purpose language, they either write the lexer and the rest of
the tools in the new language itself, or they use C++.
I'm not talking about experimentation.
Actually I'm starting to wonder whether you use C much at all, and why.
You come across as a Python and C++ 'fan-boy'.
On 18/06/2024 14:39, James Kuyper wrote:
On 17/06/2024 21:24, bart wrote:
...
If you don't need optimised code right now, why would you invoke gcc
rather than tcc? It's a no-brainer.
On virtually every occasion when I've heard someone claim that a given
decision is a no-brainer, I would generally make a different decision if
I actually applied my brain to the issue. This is no exception.
So your brain would tell you to choose a tool which takes at least 10
times as long to do the same task?
On Mon, 17 Jun 2024 07:30:44 -0000 (UTC)
Kaz Kylheku <643-408-1753@kylheku.com> wrote:
On 2024-06-17, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
The problem is that Bart's compiler is VERY unusual. It's
customized for his use, and he has lots of quirks in the way he
thinks compilers should work, which are very different from those
of most other programmers. In particular, compilation speed is very
important to him, while execution speed is almost completely
unimportant, which is pretty much the opposite of the way most
programmers prioritize those things.
Most programmers use Javascript and Python, which follow Bart's
priorities. Fast, invisible compilation to some kind of byte code
(plus possibly later JIT), slow execution time.
I'd dare to say that most programmers care about speed of compilation
more than they care about speed of execution even (or especially) when
they use "visible" compilation processes. Except when compilation is
already very fast.
BTW, my impression was that Bart's 'C' compiler uses 'visible'
compilation.
Then again, neither speed of compilation nor speed of execution are top priorities for most pros. My guess is that #1 priority is conformance
with co-workers/employer, #2 is convenient IDE, preferably integrated
with debugger, #3 is support, but there is big distance between #2, and
#3. #4 are religious issues of various forms. Speed of compilation is at best #5.
bart <bc@freeuk.com> writes:
On 18/06/2024 14:39, James Kuyper wrote:
On 17/06/2024 21:24, bart wrote:
...
If you don't need optimised code right now, why would you invoke gcc
rather than tcc? It's a no-brainer.
On virtually every occasion when I've heard someone claim that a given
decision is a no-brainer, I would generally make a different decision if >>> I actually applied my brain to the issue. This is no exception.
So your brain would tell you to choose a tool which takes at least 10
times as long to do the same task?
No, "the task" isn't "compile a program", it's "develop a program",
which includes only a quite negligible amount of time spent compiling it. What I know about TCC is relatively limited, but the Wikipedia article
is consistent with what I though I knew. It says that tcc supports all
of the features of C90, most of C99, and some gnu extensions. That is
not the dialect of C I want to write in. I want full conformance with
the latest official version of C, with any unintentional use of gnu extensions flagged with a diagnostic.
Having to write my code in a crippled version of C would be a waste of
my time, and having to fix it to take advantage of the features of a
more modern version of C when I'm ready to optimize it would be a
further waste of time. I'd save far more development time by writing in
the same dialect of C from the very beginning, then I could ever
possibly save by dividing entirely negligible compile times by a factor
of 10.
On 18/06/2024 14:39, James Kuyper wrote:
On 17/06/2024 21:24, bart wrote:
...
If you don't need optimised code right now, why would you invoke gcc
rather than tcc? It's a no-brainer.
On virtually every occasion when I've heard someone claim that a given
decision is a no-brainer, I would generally make a different decision if
I actually applied my brain to the issue. This is no exception.
So your brain would tell you to choose a tool which takes at least 10
times as long to do the same task?
if n % 2 == 1 :
       median = sorted(data)[n // 2]
else :
       median = sum(sorted(data)[(n // 2 - 1) : (n // 2 + 1)]) / 2
On 17/06/2024 12:30, bart wrote:
On 17/06/2024 07:22, James Kuyper wrote:
On 6/13/24 10:43, Michael S wrote:
On Thu, 13 Jun 2024 13:53:54 +0200...
David Brown <david.brown@hesbynett.no> wrote:
I know more than most C programmers about how certain C compilers
work, and what works well with them, and what is relevant for them - >>>>> though I certainly don't claim to know everything. Obviously Bart
knows vastly more about how /his/ compiler works. He also tends to
do testing with several small and odd C compilers, which can give
interesting results even though they are of little practical
relevance for real-world C development work.
Since he do compilers himself, he has much better feeling [that you
or me] of what is hard and what is easy, what is small and what is big, >>>> what is fast and what is slow. That applies to all compilers except
those that are very unusual. "Major" compiler are not unusual at all.
The problem is that Bart's compiler is VERY unusual. It's customized for >>> his use, and he has lots of quirks in the way he thinks compilers should >>> work, which are very different from those of most other programmers.
In
particular, compilation speed is very important to him, while execution
speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
Compilation speed is important to everyone. That's why so many tricks
are used to get around the lack of speed in a big compiler, or so many
extra resources are thrown at the problem.
What "tricks" ?
That depends on the language, type of code, and target platform. Typical
C code on an x86_64 platform might be two or three times slower when
using a poorly optimising compiler. After all, the designers of x86
cpus put a great deal of effort into making shitty code run fast.
DFS wrote:
On 6/18/2024 12:11 PM, David Brown wrote:
if n % 2 == 1 :
        median = sorted(data)[n // 2]
else :
        median = sum(sorted(data)[(n // 2 - 1) : (n // 2 + 1)]) / 2
I think your else formula (n % 2 == 0) is incorrect:
n     = 4
data  = [1,2,3,4]
median = 2.5
Yours appears to sum (1,2,3) = 6 / 2 = 3.
Am I reading it correctly?
Python ranges include the start index but exclude the end index. So data[1:3] gives the items at data[1] and data[2], but not data[3].
Indexes are zero-based, so data[1:3] == [2, 3], sum([2, 3]) == 5, and 5
/ 2 == 2.5.
On 18/06/2024 13:36, David Brown wrote:
#!/usr/bin/python3And here's a simple task for you. Our filesystem uses a new technology
import sys
if len(sys.argv) < 2 :
     print("Usage: sums.py <input-file>")
     sys.exit(1)
data = list(map(int, open(sys.argv[1], "r").read().split()))
n = len(data)
s = sum(data)
print("Count: %i, sum %i, average %i" % (n, s, s // n))
and is a bit dicey. Occasionally you will get a read error. Can you
modify the python to print out that a read error has occurred?
On 6/18/2024 12:11 PM, David Brown wrote:
if n % 2 == 1 :
        median = sorted(data)[n // 2]
else :
        median = sum(sorted(data)[(n // 2 - 1) : (n // 2 + 1)]) / 2
I think your else formula (n % 2 == 0) is incorrect:
n     = 4
data  = [1,2,3,4]
median = 2.5
Yours appears to sum (1,2,3) = 6 / 2 = 3.
Am I reading it correctly?
If compilation was instant, half the reasons for a makefile and its dependency graphs would disappear.
On 18/06/2024 16:40, Michael S wrote:
On Tue, 18 Jun 2024 14:36:40 +0200My main experience of Python was that we had some resource files which
David Brown <david.brown@hesbynett.no> wrote:
Of course if you don't know Python, it will be slower to write it in
Python!
I don't know Python well, but it does not meant that I don't know it at
all.
Few minutes ago I took a look into docs and it seems that situation with
writing binary data files with predefined layout is better than what I
was suspecting. They have something called "Buffer Protocol". It allows
to specify layout in declarative manner, similarly to C struct or may
be even to Ada's records with representation clause.
However attempt to read the doc page further down proved that my
suspicion about steepness of the learning curve was not wrong :(
were icons, in matching light and dark themes. The light theme had
suffix _L followed by extension, and the dark themes had _D. And they
needed to be sorted alphabetically, except that _L should be placed
before _D.
And it didn't take long to get Python to sort the list alphabetically,
but there seemed no way in to the sort comparision function itself. And
I had to give up.
On Tue, 18 Jun 2024 14:36:40 +0200
David Brown <david.brown@hesbynett.no> wrote:
Of course if you don't know Python, it will be slower to write it in
Python!
I don't know Python well, but it does not meant that I don't know it at
all.
Few minutes ago I took a look into docs and it seems that situation with writing binary data files with predefined layout is better than what I
was suspecting. They have something called "Buffer Protocol". It allows
to specify layout in declarative manner, similarly to C struct or may
be even to Ada's records with representation clause.
However attempt to read the doc page further down proved that my
suspicion about steepness of the learning curve was not wrong :(
On 17/06/2024 14:43, David Brown wrote:
On 17/06/2024 12:30, bart wrote:
On 17/06/2024 07:22, James Kuyper wrote:
On 6/13/24 10:43, Michael S wrote:
On Thu, 13 Jun 2024 13:53:54 +0200...
David Brown <david.brown@hesbynett.no> wrote:
The problem is that Bart's compiler is VERY unusual. It's customizedI know more than most C programmers about how certain C compilers
work, and what works well with them, and what is relevant for them - >>>>>> though I certainly don't claim to know everything. Obviously Bart
knows vastly more about how /his/ compiler works. He also tends to >>>>>> do testing with several small and odd C compilers, which can give
interesting results even though they are of little practical
relevance for real-world C development work.
Since he do compilers himself, he has much better feeling [that you
or me] of what is hard and what is easy, what is small and what is
big,
what is fast and what is slow. That applies to all compilers except
those that are very unusual. "Major" compiler are not unusual at all. >>>>
for
his use, and he has lots of quirks in the way he thinks compilers
should
work, which are very different from those of most other programmers.
In
particular, compilation speed is very important to him, while execution >>>> speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
Compilation speed is important to everyone. That's why so many tricks
are used to get around the lack of speed in a big compiler, or so
many extra resources are thrown at the problem.
What "tricks" ?
Going to considerable lengths to avoid actually doing any compilation,
or to somehow cache previous results (I mean things like .pch files
rather than .o files).
Have a look at any makefile.
If compilation was instant, half the reasons for a makefile and its dependency graphs would disappear.
For the scale of programs I write, with the tools I use, compilation
*is* more or less instant.
(Roughly 0.1 seconds; faster than it takes to press and release the
Enter key, for my main compiler. My C compiler takes a bit longer, as it
has been accelerated, but it tends to be used for smaller projects if it
is something I've written.)
That depends on the language, type of code, and target platform.
Typical C code on an x86_64 platform might be two or three times
slower when using a poorly optimising compiler. After all, the
designers of x86 cpus put a great deal of effort into making shitty
code run fast.
Yes, that's one reason why you can get away without an optimiser, for sensibly written source code. But it also makes reasoning about optimal
code much harder: removing superfluous instructions often makes code
slower!
On 18/06/2024 23:49, Keith Thompson wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:key specifies a function of one argument that is used to extract a
[...]
And it didn't take long to get Python to sort the list alphabetically,
but there seemed no way in to the sort comparision function
itself. And I had to give up.
<OT>
https://docs.python.org/3/library/functions.html#sorted
https://docs.python.org/3/library/stdtypes.html#list.sort
</OT>
comparison key from each element in iterable (for example,
key=str.lower). The default value is None (compare the elements directly).
You see the problem. I can sort on any field. I can sort alphaetically upwards and downwards. But I don't want to do that. I want to use a non-alphabetical comaprison function on two fields, and I need to
specify that myself, because it's impossible that it is available
anywhere. And that is to sort alphalbetically, except where the strings
match except for an emedded "_L_" or "_D_" where the string wth the
embedded "L" shoud be treated as closer to A than the string with the emebdded "_D_".
And I'm sure there is some way to achiev e this. But in C, it s achieved simply by declaring that qsort takes a function pointer to user-supplied code.
On 18/06/2024 20:22, bart wrote:
On 17/06/2024 14:43, David Brown wrote:
On 17/06/2024 12:30, bart wrote:
On 17/06/2024 07:22, James Kuyper wrote:
On 6/13/24 10:43, Michael S wrote:
On Thu, 13 Jun 2024 13:53:54 +0200...
David Brown <david.brown@hesbynett.no> wrote:
The problem is that Bart's compiler is VERY unusual. It'sI know more than most C programmers about how certain C compilers >>>>>>> work, and what works well with them, and what is relevant for them - >>>>>>> though I certainly don't claim to know everything. Obviously Bart >>>>>>> knows vastly more about how /his/ compiler works. He also tends to >>>>>>> do testing with several small and odd C compilers, which can give >>>>>>> interesting results even though they are of little practical
relevance for real-world C development work.
Since he do compilers himself, he has much better feeling [that you >>>>>> or me] of what is hard and what is easy, what is small and what is >>>>>> big,
what is fast and what is slow. That applies to all compilers except >>>>>> those that are very unusual. "Major" compiler are not unusual at all. >>>>>
customized for
his use, and he has lots of quirks in the way he thinks compilers
should
work, which are very different from those of most other programmers.
In
particular, compilation speed is very important to him, while
execution
speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
Compilation speed is important to everyone. That's why so many
tricks are used to get around the lack of speed in a big compiler,
or so many extra resources are thrown at the problem.
What "tricks" ?
Going to considerable lengths to avoid actually doing any compilation,
or to somehow cache previous results (I mean things like .pch files
rather than .o files).
Have a look at any makefile.
As I suspected, your idea of "tricks" is mostly what other people call
useful or essential tools.
I would use makefiles even if compilation was instant. I /do/ use
makefiles even when compilation is near instant. I use them even if
every run requires a full rebuild of everything. I use them for all
kinds of tasks other than compiling C - I first started using them for cross-assembly builds on DOS.
The point of a makefile (or other build system) is twofold:
1. Get consistent results, with minimal risk of sometimes getting the
build process wrong.
2. Save time and effort for the developer.
It takes a special kind of dedication and stubborn, wilful ignorance to
fail to see the benefit of build tools. (make is not the only option available.)
If compilation was instant, half the reasons for a makefile and its
dependency graphs would disappear.
My makefiles would be simpler if compilation were instant, but they
would be equally essential to my work.
For the scale of programs I write, with the tools I use, compilation
*is* more or less instant.
Some of us write serious code, use serious tools, and use them in
serious ways.
On 19/06/2024 09:05, David Brown wrote:
Some of us write serious code, use serious tools, and use them in
serious ways.
I understand.
Yes, but that's not quite what we want. A typical input would go.
On 19/06/2024 18:49, David Brown wrote:
On 19/06/2024 18:52, Malcolm McLean wrote:This was a work project, so "we". I would never set up such a system.
Yes, but that's not quite what we want. A typical input would go.
It's extremely hard to guess what you want (not "we", but "you" - no
one else wants this kind of thing) when you have bizarre requirements
and only give bits of them. So modifying the Python code is left as
an exercise if you are interested, especially as it is off-topic.
But we hasd light-themed and dark-themed icons and they hsd to be
arranged just so so that the program would find them and show the right theme. And as you can imagine, it was a nuisance to we programmers to
set up the resource scripts so that eveything was right.
So why not get Python to do the job? But there wasn't much enthusiasm.
So, despite not knowing Python, I decided to have a go, and I got a
sorted list of icons quite easily, and it looked promising. But now the special requirement for a little deviation from alphabetical sort. And I couldn't work out how to do that.
And it wasn't what I was supposed to be doing or paid to do. We used to
have a weekly meeting where we discussed work done. If I said "oh, and I spent an afternoon knocking up this little Python script to help get
those resource files together", then that's OK. If I say that was my
main focus for the week, no, and if I say I spent substantial time on it
and it didn't even work - well that really wouldn't go down well.
So I had to abandon it once it became clear that it would take many
hours of trawling through docs and online tips to try to work out a way.
And no-one has posted a solution here. And, whilst there will be a way,
I suspect that it just doesn't use the mainstream langage facilities. I suspect that Python isn't really a programming language - a language
designed to make it easy to apply arbitrary transforms to data - it's a scripting language - a language designed to make it easy to call pre-existings code to do the things it is designed to do.
But maybe I'm unfair.
On 19/06/2024 18:49, David Brown wrote:
On 19/06/2024 18:52, Malcolm McLean wrote:This was a work project, so "we". I would never set up such a system.
Yes, but that's not quite what we want. A typical input would go.
It's extremely hard to guess what you want (not "we", but "you" - no
one else wants this kind of thing) when you have bizarre requirements
and only give bits of them. So modifying the Python code is left as
an exercise if you are interested, especially as it is off-topic.
But we hasd light-themed and dark-themed icons and they hsd to be
arranged just so so that the program would find them and show the right theme. And as you can imagine, it was a nuisance to we programmers to
set up the resource scripts so that eveything was right.
So why not get Python to do the job? But there wasn't much enthusiasm.
So, despite not knowing Python, I decided to have a go, and I got a
sorted list of icons quite easily, and it looked promising. But now the special requirement for a little deviation from alphabetical sort. And I couldn't work out how to do that.
And it wasn't what I was supposed to be doing or paid to do. We used to
have a weekly meeting where we discussed work done. If I said "oh, and I spent an afternoon knocking up this little Python script to help get
those resource files together", then that's OK. If I say that was my
main focus for the week, no, and if I say I spent substantial time on it
and it didn't even work - well that really wouldn't go down well.
So I had to abandon it once it became clear that it would take many
hours of trawling through docs and online tips to try to work out a way.
And no-one has posted a solution here. And, whilst there will be a way,
I suspect that it just doesn't use the mainstream langage facilities. I suspect that Python isn't really a programming language - a language
designed to make it easy to apply arbitrary transforms to data - it's a scripting language - a language designed to make it easy to call pre-existings code to do the things it is designed to do.
But maybe I'm unfair.
On 19/06/2024 21:42, Malcolm McLean wrote:
On 19/06/2024 18:49, David Brown wrote:
On 19/06/2024 18:52, Malcolm McLean wrote:This was a work project, so "we". I would never set up such a system.
Yes, but that's not quite what we want. A typical input would go.
It's extremely hard to guess what you want (not "we", but "you" - no
one else wants this kind of thing) when you have bizarre requirements
and only give bits of them. So modifying the Python code is left as
an exercise if you are interested, especially as it is off-topic.
But we hasd light-themed and dark-themed icons and they hsd to be
arranged just so so that the program would find them and show the
right theme. And as you can imagine, it was a nuisance to we
programmers to set up the resource scripts so that eveything was right.
So why not get Python to do the job? But there wasn't much enthusiasm.
So, despite not knowing Python, I decided to have a go, and I got a
sorted list of icons quite easily, and it looked promising. But now
the special requirement for a little deviation from alphabetical sort.
And I couldn't work out how to do that.
And it wasn't what I was supposed to be doing or paid to do. We used
to have a weekly meeting where we discussed work done. If I said "oh,
and I spent an afternoon knocking up this little Python script to help
get those resource files together", then that's OK. If I say that was
my main focus for the week, no, and if I say I spent substantial time
on it and it didn't even work - well that really wouldn't go down well.
So I had to abandon it once it became clear that it would take many
hours of trawling through docs and online tips to try to work out a
way. And no-one has posted a solution here. And, whilst there will be
a way, I suspect that it just doesn't use the mainstream langage
facilities. I suspect that Python isn't really a programming language
- a language designed to make it easy to apply arbitrary transforms to
data - it's a scripting language - a language designed to make it easy
to call pre-existings code to do the things it is designed to do.
But maybe I'm unfair.
No; I don't like Python either. It's big. It has lots of advanced, hard-to-grasp features. There's a dozen unwieldy, usually incompatible
ways of getting anything done.
Pretty much everything can be assigned to (the only exception is
reserved words). Because every user identifer (even if declared with def
or class or module) is a variable.
Take a simple feature like a struct with mutable fields:
  typedef struct {int x, y;} Point;
How do you do that in Python; maybe a class:
  class Point:
      pass
  p = Point()            # create an instance
  p.x = 100              # fill in the fields
  p.qwghheghergh = 200
But here you type gobbledygook instead of 'y'; it still works! You can
have an unlimited number of attributes.
Maybe a tuple is better, but those are indexed by number, not by name.
So you use a module providing NamedTuples - except those fields are immutable. You can only update the lot.
p = Point(2, 3)
p2 = p._replace(x = 45)
Here's one I've just seen (that '@' line is a 'decorator'; don't ask me
what it means):
 from dataclasses import dataclass
 @dataclass
 class Point:
    x: int
    y: int
 p = Point(10, 20)
 print (p)
This looks promising. Then I tried 'p.z = 30'; it still works.
So does:
 p = Point("dog", "cat")     # what happened to those int types?
Maybe you need a struct type compatible with C; then you might try this:
 from ctypes import *
 class YourStruct(Structure):         # adapted from online example
     _fields_ = [('x', c_int),
                 ('y', c_int)]
It's just a big, ugly, kitchen-sink language. They throw in every
feature they can think of (like C++, possibly why DB likes it) in the
hope that somewhere in the mess is a solution to your needs.
I'm not surprised it takes 20MB to embed.
On 20/06/2024 08:55, David Brown wrote:...
You've made it clear you know nothing about the language. Fair enough -Yes but I just don't.
we all know almost nothing about almost all programming languages. But
trust someone who does.
Everyone says "oh yes, that is easy - goto a Python group" and so
on. No-one actually comes up with the code.
In C, what we do is write a special version of strcmp
int strcmp_light_and_dark(const char *a, const char *b)
{
int i;
for (i = 0; a[i] && b[i]; i++)
{
if (a[i] != b[i])
{
if (a[i] == 'L' && b[i] == 'D' && i > 0 && a[i-1] == '_')
return -1;
if (a[i] == 'D' && b[i] == 'L' && i > 0 && a[i-1] = '_')
return 1;
break;
}
}
return a[i] - b[i];
}
So easy to do.
On 20/06/2024 08:55, David Brown wrote:
On 19/06/2024 22:42, Malcolm McLean wrote:Yes but I just don't.
On 19/06/2024 18:49, David Brown wrote:
On 19/06/2024 18:52, Malcolm McLean wrote:This was a work project, so "we". I would never set up such a system.
Yes, but that's not quite what we want. A typical input would go.
It's extremely hard to guess what you want (not "we", but "you" - no
one else wants this kind of thing) when you have bizarre
requirements and only give bits of them. So modifying the Python
code is left as an exercise if you are interested, especially as it
is off-topic.
But we hasd light-themed and dark-themed icons and they hsd to be
arranged just so so that the program would find them and show the
right theme. And as you can imagine, it was a nuisance to we
programmers to set up the resource scripts so that eveything was right.
So why not get Python to do the job? But there wasn't much
enthusiasm. So, despite not knowing Python, I decided to have a go,
and I got a sorted list of icons quite easily, and it looked
promising. But now the special requirement for a little deviation
from alphabetical sort. And I couldn't work out how to do that.
And it wasn't what I was supposed to be doing or paid to do. We used
to have a weekly meeting where we discussed work done. If I said "oh,
and I spent an afternoon knocking up this little Python script to
help get those resource files together", then that's OK. If I say
that was my main focus for the week, no, and if I say I spent
substantial time on it and it didn't even work - well that really
wouldn't go down well.
So I had to abandon it once it became clear that it would take many
hours of trawling through docs and online tips to try to work out a
way. And no-one has posted a solution here. And, whilst there will be
a way, I suspect that it just doesn't use the mainstream langage
facilities. I suspect that Python isn't really a programming language
- a language designed to make it easy to apply arbitrary transforms
to data - it's a scripting language - a language designed to make it
easy to call pre-existings code to do the things it is designed to do.
But maybe I'm unfair.
It's not so much that you are being unfair, it is that you are arguing
from a position of almost total ignorance. It's fine to say you know
little about Python and can't comment much on it. It is /not/ fine to
say (and demonstrate) that you know almost nothing about a language
and then make wild claims about what it can and cannot do.
This is not a Python group, so I have not bothered writing code for
your weird requirements. Suffice it to say that it would not be hard,
and it would use "mainstream language facilities" (I take that to mean
the language and its standard libraries, rather than third-party tools).
Yes, Python is a "programming language" by any reasonable definition
of that term. (It is /also/ useful as a scripting language -
languages can be suitable for more than one task.)Â Yes, it is
designed to make it easy to "apply arbitrary transforms to data" - it
is usually very much easier to do this than in C, at the cost of less
efficient run-time performance. And no language has pre-existing code
or standard functions to handle your highly unusual sorting
requirements - such things always need their own code.
You've made it clear you know nothing about the language. Fair enough
- we all know almost nothing about almost all programming languages.
But trust someone who does.
Everyone says "oh yes, that is easy - goto a Python group" and so on.
No-one actually comes up with the code.
In C, what we do is write a special version of strcmp
int strcmp_light_and_dark(const char *a, const char *b)
{
   int i;
   for (i = 0; a[i] && b[i]; i++)
   {
       if (a[i] != b[i])
       {
          if (a[i] == 'L' && b[i] == 'D' && i > 0 && a[i-1] == '_')
              return -1;
           if (a[i] == 'D' && b[i] == 'L' && i > 0 && a[i-1] = '_')
              return 1;
          break;
       }
   }
   return a[i] - b[i];
}
So easy to do. And we can't pass that to qsort. We have to write a
little wrapper to convert the pointers for us.
But C hs that sort of flexibility as a result of stripping features away
from the language.
On 19/06/2024 23:51, bart wrote:
Pretty much everything can be assigned to (the only exception is
reserved words). Because every user identifer (even if declared with
def or class or module) is a variable.
The concept of "variable" in Python is quite different from that of C.
You can pretend they are similar for very simple Python snippets, but
then you will end up thinking there are lots of arbitrary rules for when assignment and function parameters are by value or by reference. It is better to think that all "things" in Python are anonymous
reference-counted objects on the heap. When it looks like you have a variable, you actually just have a named reference to such objects.
Imagine it more like your "variables" are all "void *" pointers or references, while all other types and structures are malloc'd. These references have no type information - but the objects they point to are
all strongly typed. And the objects have reference-counted garbage collection.
That is a way to make structures for interaction with external code - basically, for when you are connecting to DLLs or so libraries.
It's just a big, ugly, kitchen-sink language. They throw in every
feature they can think of (like C++, possibly why DB likes it) in the
hope that somewhere in the mess is a solution to your needs.
I'm not surprised it takes 20MB to embed.
Neither Python nor C++ throws in "every feature they can think of" - for
both languages, there is a long process of proposals, discussions,
testing, and consideration of the impact on the rest of the language, existing code, and possible future language features, before a feature
is included.
 Yes, these are big languages. Sometimes big is good,
sometimes it is bad - it would be wildly foolish to think that one
language, or one style of language, is all that people need or want.
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
On 20/06/2024 08:55, David Brown wrote:
...
You've made it clear you know nothing about the language. Fair enough - >>> we all know almost nothing about almost all programming languages. But
trust someone who does.
Yes but I just don't.
Everyone says "oh yes, that is easy - goto a Python group" and so
on. No-one actually comes up with the code.
In C, what we do is write a special version of strcmp
int strcmp_light_and_dark(const char *a, const char *b)
{
int i;
for (i = 0; a[i] && b[i]; i++)
{
if (a[i] != b[i])
{
if (a[i] == 'L' && b[i] == 'D' && i > 0 && a[i-1] == '_')
return -1;
if (a[i] == 'D' && b[i] == 'L' && i > 0 && a[i-1] = '_')
return 1;
break;
}
}
return a[i] - b[i];
}
So easy to do.
Unless I'm missing something here, that code does not do what you say
you want. You gave an example of some input and the desired output but
this comparison function does not sort into the ordering you gave.
You may find this "ordering" hard to duplicate in other languages
because it is not even an ordering in the mathematical sense as it is
not transitive.
Can you specify the desired ordering as a total or partial order
relation?
On a C language point, I don't think the standard says anything about
sorting with non-order functions like the one above.
Is an
implementation of qsort permitted to misbehave (for example by not terminating) when the comparison function does not implement a proper
order relation?
On 20/06/2024 11:34, David Brown wrote:
On 19/06/2024 23:51, bart wrote:
[Discussing Python]
Pretty much everything can be assigned to (the only exception is
reserved words). Because every user identifer (even if declared with
def or class or module) is a variable.
The concept of "variable" in Python is quite different from that of C.
You can pretend they are similar for very simple Python snippets, but
then you will end up thinking there are lots of arbitrary rules for
when assignment and function parameters are by value or by reference.
It is better to think that all "things" in Python are anonymous
reference-counted objects on the heap. When it looks like you have a
variable, you actually just have a named reference to such objects.
Imagine it more like your "variables" are all "void *" pointers or
references, while all other types and structures are malloc'd. These
references have no type information - but the objects they point to
are all strongly typed. And the objects have reference-counted
garbage collection.
You haven't given an opinion. I think this is an unnecessary aspect of
it, which also makes it harder to optimise, and to reason about.
My languages have perhaps a dozen categories of identifiers, known at compile-time, which include variable names. Python has only one, a 'variable'. It mean this is possible:
   def F(n): return n + 1
   ...
   F = 42
   ....
   F(x)               # will not work when F is 42
Neither Python nor C++ throws in "every feature they can think of" -
for both languages, there is a long process of proposals, discussions,
testing, and consideration of the impact on the rest of the language,
existing code, and possible future language features, before a feature
is included.
And /then/ they include the feature! I've long given up keeping track.
Both have mutable elements. Neither allow arbitrary attributes (so
impossible to misspell member names). And if the FFI demands it,
pointers to structs or ints can be passed.
But Python even then completely disregarded performance. In the 1990s,
if you wrote a loop like this:
   for i in range(1000000):
       ....
it would actually create an object with a million elements so that you
could iterate along it. It sounds absolutely crazy, and it was.
Later they added xrange() which didn't do that, and later on 'xrange'
morphed into 'range'.
On 20/06/2024 15:37, bart wrote:
On 20/06/2024 11:34, David Brown wrote:
I've only been discussing Python as an example of how many programming
tasks are easier in high-level languages than in C.
I seem to remember you getting really worked up about C programmers
using the same identifier for structs and variables!
Both have mutable elements. Neither allow arbitrary attributes (so
impossible to misspell member names). And if the FFI demands it,
pointers to structs or ints can be passed.
You can do all this with Python. I showed you how to have structures
with mutable elements - and immutable structures, and structures with or without the ability to add new fields.
But Python even then completely disregarded performance. In the 1990s,
if you wrote a loop like this:
    for i in range(1000000):
        ....
it would actually create an object with a million elements so that you
could iterate along it. It sounds absolutely crazy, and it was.
Later they added xrange() which didn't do that, and later on 'xrange'
morphed into 'range'.
So your complaint now is that newer versions of Python have made some
common tasks more efficient? There's no pleasing some people.
Incidentally you might like the default sort in my ls command, now in
the Baby X FileSystem shell. There's also a separate programs that runs
under the native shell - of course I developed the command on native
host filesystems first. It uses a natural sort so that "Chapter 10"
sorts after and not before "Chapter 2".
Spaces have no place in filenames.
On 20/06/2024 16:07, David Brown wrote:
On 20/06/2024 15:37, bart wrote:
On 20/06/2024 11:34, David Brown wrote:
I've only been discussing Python as an example of how many
programming tasks are easier in high-level languages than in C.
A lot of it seems to be incantations that you can only come up as an
expert user. I wouldn't have been able to come up with even basic file-reading; I'd have to go and look up examples, every time.
I seem to remember you getting really worked up about C programmers
using the same identifier for structs and variables!
Yes, you can have both 'struct T' and a type, variable etc called
'T'; or a type 'T' and, due to case sensitivity, a variable or
function called 't'.
But those identifiers in C are still fixed at compile-time. You can't
so this:
printf = sqrt;
In Python (not 2.x where 'print' was a reserved word), you can:
print = math.sqrt
Both have mutable elements. Neither allow arbitrary attributes (so
impossible to misspell member names). And if the FFI demands it,
pointers to structs or ints can be passed.
You can do all this with Python. I showed you how to have
structures with mutable elements - and immutable structures, and
structures with or without the ability to add new fields.
I mentioned 5 ways of doing it, you added one or two more. That is my
point: when a simple feature isn't built in, solutions have to be
provided in lots of disparate ways.
I think your last one corresponded most to what I already have in my language, but it needed 3 special features to do it, plus maybe one
more to hide some of those workings.
Python is supposed to a good beginner's language not a DIY one.
On Thu, 20 Jun 2024 17:58:25 +0100
bart <bc@freeuk.com> wrote:
Python is supposed to a good beginner's language not a DIY one.
Python + its huge standard library is supposed to a good beginner's language. Not the language in isolation.
On 6/20/24 13:45, Scott Lurndal wrote:
...
Spaces have no place in filenames.
Unix-like OSs and Windows both allow them, and they are used frequently.
On 2024-06-17, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
The problem is that Bart's compiler is VERY unusual. It's customized for
his use, and he has lots of quirks in the way he thinks compilers should
work, which are very different from those of most other programmers. In
particular, compilation speed is very important to him, while execution
speed is almost completely unimportant, which is pretty much the
opposite of the way most programmers prioritize those things.
Most programmers use Javascript and Python, which follow Bart's
priorities. Fast, invisible compilation to some kind of byte code (plus possibly later JIT), slow execution time.
I do my C development with optimisations enabled, which means that the C compiler will obey all the rules and requirements of C. Optimisations
don't change the meaning of correct code - they only have an effect on
the results of your code if you have written incorrect code. I don't
know about you, but my aim in development is to write /correct/ code. If disabling optimisations helped in some way, it would be due to bugs and
luck.
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
Incidentally you might like the default sort in my ls command, now in
the Baby X FileSystem shell. There's also a separate programs that runs
under the native shell - of course I developed the command on native
host filesystems first. It uses a natural sort so that "Chapter 10"
sorts after and not before "Chapter 2".
Spaces have no place in filenames.
chapter02 sorts efore chapter10 naturally.
Compilation speed is important to everyone. That's why so many tricks
are used to get around the lack of speed in a big compiler, or so many
extra resources are thrown at the problem.
What "tricks" ?
On 20/06/2024 16:07, David Brown wrote:
On 20/06/2024 15:37, bart wrote:
On 20/06/2024 11:34, David Brown wrote:
I've only been discussing Python as an example of how many programming
tasks are easier in high-level languages than in C.
A lot of it seems to be incantations that you can only come up as an
expert user. I wouldn't have been able to come up with even basic file-reading; I'd have to go and look up examples, every time.
I seem to remember you getting really worked up about C programmers
using the same identifier for structs and variables!
Yes, you can have both 'struct T' and a type, variable etc called 'T';
or a type 'T' and, due to case sensitivity, a variable or function
called 't'.
But those identifiers in C are still fixed at compile-time. You can't so this:
   printf = sqrt;
In Python (not 2.x where 'print' was a reserved word), you can:
   print = math.sqrt
Both have mutable elements. Neither allow arbitrary attributes (so
impossible to misspell member names). And if the FFI demands it,
pointers to structs or ints can be passed.
You can do all this with Python. I showed you how to have structures
with mutable elements - and immutable structures, and structures with
or without the ability to add new fields.
I mentioned 5 ways of doing it, you added one or two more. That is my
point: when a simple feature isn't built in, solutions have to be
provided in lots of disparate ways.
I think your last one corresponded most to what I already have in my language, but it needed 3 special features to do it, plus maybe one more
to hide some of those workings.
Python is supposed to a good beginner's language not a DIY one.
But Python even then completely disregarded performance. In the
1990s, if you wrote a loop like this:
    for i in range(1000000):
        ....
it would actually create an object with a million elements so that
you could iterate along it. It sounds absolutely crazy, and it was.
Later they added xrange() which didn't do that, and later on 'xrange'
morphed into 'range'.
So your complaint now is that newer versions of Python have made some
common tasks more efficient? There's no pleasing some people.
No, the complaint was getting it so wrong in the first place, then
taking too long to fix it. (I think it was in Python 3 that you could
type 'range' instead of 'xrange'.)
Ben Bacarisse <ben@bsb.me.uk> writes:
[...]
On a C language point, I don't think the standard says anything about
sorting with non-order functions like the one above. Is an
implementation of qsort permitted to misbehave (for example by not
terminating) when the comparison function does not implement a proper
order relation?
N1570 7.22.5p4 (applies to bsearch and qsort):
"""
When the same objects (consisting of size bytes, irrespective of
their current positions in the array) are passed more than once to
the comparison function, the results shall be consistent with one
another. That is, for qsort they shall define a total ordering on
the array, and for bsearch the same object shall always compare
the same way with the key.
"""
That's a "shall" outside a constraint, so violating it results in
undefined behavior.
On 20/06/2024 12:24, Ben Bacarisse wrote:
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
On 20/06/2024 08:55, David Brown wrote:...
Unless I'm missing something here, that code does not do what you sayYou've made it clear you know nothing about the language. Fair enough - >>>> we all know almost nothing about almost all programming languages. But >>>> trust someone who does.Yes but I just don't.
Everyone says "oh yes, that is easy - goto a Python group" and so
on. No-one actually comes up with the code.
In C, what we do is write a special version of strcmp
int strcmp_light_and_dark(const char *a, const char *b)
{
int i;
for (i = 0; a[i] && b[i]; i++)
{
if (a[i] != b[i])
{
if (a[i] == 'L' && b[i] == 'D' && i > 0 && a[i-1] == '_')
return -1;
if (a[i] == 'D' && b[i] == 'L' && i > 0 && a[i-1] = '_')
return 1;
break;
}
}
return a[i] - b[i];
}
So easy to do.
you want. You gave an example of some input and the desired output but
this comparison function does not sort into the ordering you gave.
You may find this "ordering" hard to duplicate in other languagesIt's allowed to crash because it runs out of stack space if the sort
because it is not even an ordering in the mathematical sense as it is
not transitive.
Can you specify the desired ordering as a total or partial order
relation?
On a C language point, I don't think the standard says anything about
sorting with non-order functions like the one above. Is an
implementation of qsort permitted to misbehave (for example by not
terminating) when the comparison function does not implement a proper
order relation?
function isb't consistent.
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
[...]
On a C language point, I don't think the standard says anything
about sorting with non-order functions like the one above. Is an
implementation of qsort permitted to misbehave (for example by not
terminating) when the comparison function does not implement a
proper order relation?
N1570 7.22.5p4 (applies to bsearch and qsort):
"""
When the same objects (consisting of size bytes, irrespective of
their current positions in the array) are passed more than once to
the comparison function, the results shall be consistent with one
another. That is, for qsort they shall define a total ordering on
the array, and for bsearch the same object shall always compare
the same way with the key.
"""
That's a "shall" outside a constraint, so violating it results in
undefined behavior.
I think it should be clearer. What the "that is" phrase seems to
clarify in no way implies a total order, merely that the repeated
comparisons or the same elements are consistent with one another.
That the comparison function defines a total order on the elements
is, to me, a major extra constraint that should not be written as an
apparent clarification to something the does not imply it: repeated
calls should be consistent with one another and, in addition, a total
order should be imposed on the elements present.
On 20/06/2024 18:58, bart wrote:
No, the complaint was getting it so wrong in the first place, then
taking too long to fix it. (I think it was in Python 3 that you could
type 'range' instead of 'xrange'.)
s = 0
for i in range(10000000) :
    s = s + i
print(s)
(I made it 10 million, not 1 million, because I have such a vastly
faster computer than everyone else.)
$ time python2 sum.py
49999995000000
real   0m0,820s
user   0m0,632s
sys   0m0,179s
$ time python3 sum.py
49999995000000
real   0m0,868s
user   0m0,854s
sys   0m0,004s
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
[...]
And I see that using Python's getkey() function to swap "_D" and "_H"
would be a way to solve this. But it's far from obvious how to set up a
custom sort.
And you still think comp.lang.c is the place to talk about it?
If the links I already posted aren't sufficiently helpful (I expected
they would be), comp.lang.python exists and is reasonably active.
Incidentally you might like the default sort in my ls command, now in
the Baby X FileSystem shell. There's also a separate programs that runs
under the native shell - of course I developed the command on native
host filesystems first. It uses a natural sort so that "Chapter 10"
sorts after and not before "Chapter 2".
GNU coreutils ls has a "-v" or "--sort=version" option that does this.
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
[...]
On a C language point, I don't think the standard says anything about
sorting with non-order functions like the one above. Is an
implementation of qsort permitted to misbehave (for example by not
terminating) when the comparison function does not implement a proper
order relation?
N1570 7.22.5p4 (applies to bsearch and qsort):
"""
When the same objects (consisting of size bytes, irrespective of
their current positions in the array) are passed more than once to
the comparison function, the results shall be consistent with one
another. That is, for qsort they shall define a total ordering on
the array, and for bsearch the same object shall always compare
the same way with the key.
"""
That's a "shall" outside a constraint, so violating it results in
undefined behavior.
I think it should be clearer. What the "that is" phrase seems to
clarify in no way implies a total order, merely that the repeated
comparisons or the same elements are consistent with one another.
On 20/06/2024 16:05, Tim Rentsch wrote:
My reading of the C standard is that the comparison function
must impose a total ordering on the elements actually present
in the array, or is undefined behavior if it does not. In
other words it's okay if the comparison function doesn't
define a proper order relation, as long as there are no
inconsistencies between values that actually occur in the
particular array being sorted.
Yes, a qsort written in the natural way can getstuck if a
sub0array it considered sorted becmes not sortted on the next
pass.
During the last 20 or more years, Python implementations have gotten
more and more efficient. So if there is a difference between range and xrange, there are techniques that can be used to minimise it.
But if should never have been done that crazy way in the first place.
However if I compare range to xrange now on Py2 using such loops as your examples, then xrange is about twice as fast. But range on Py3 is
in-between. Basically I've no idea what's going on inside it these days.
Yes, a qsort written in the natural way can getstuck if a sub0array it considered sorted becmes not sortted on the next pass.
On 17/06/2024 20:29, David Brown wrote:
I do my C development with optimisations enabled, which means that the
C compiler will obey all the rules and requirements of C.
Optimisations don't change the meaning of correct code - they only
have an effect on the results of your code if you have written
incorrect code. I don't know about you, but my aim in development is
to write /correct/ code. If disabling optimisations helped in some
way, it would be due to bugs and luck.
To me disabling optimisations does one slightly useful thing (compiles a little quicker) and one really useful one. It makes the interactive
debugger work. Optimised code confuses the debugger, especially when it
does things like reorder code, unroll loops, or merge equivalent functions.
Of course I then test with the optimised version.
Andy
On 17/06/2024 14:43, David Brown wrote:
Compilation speed is important to everyone. That's why so many tricks
are used to get around the lack of speed in a big compiler, or so
many extra resources are thrown at the problem.
What "tricks" ?
Precompiled headers sprang to mind in about half a second.
<https://en.wikipedia.org/wiki/Precompiled_header>
Andy
On 20/06/2024 22:21, Vir Campestris wrote:
On 17/06/2024 20:29, David Brown wrote:
I do my C development with optimisations enabled, which means that
the C compiler will obey all the rules and requirements of C.
Optimisations don't change the meaning of correct code - they only
have an effect on the results of your code if you have written
incorrect code. I don't know about you, but my aim in development is
to write /correct/ code. If disabling optimisations helped in some
way, it would be due to bugs and luck.
To me disabling optimisations does one slightly useful thing (compiles
a little quicker) and one really useful one. It makes the interactive
debugger work. Optimised code confuses the debugger, especially when
it does things like reorder code, unroll loops, or merge equivalent
functions.
Of course I then test with the optimised version.
Andy
I understand your viewpoint and motivation. But my own experience is
mostly different.
First, to get it out of the way, there's the speed of compilation. While heavy optimisation (-O3) can take noticeably longer, I never see -O0 as
being in any noticeable way faster for compilation than -O1 or even
-O2.
On 20/06/2024 22:31, Vir Campestris wrote:
On 17/06/2024 14:43, David Brown wrote:
Compilation speed is important to everyone. That's why so many
tricks are used to get around the lack of speed in a big compiler,
or so many extra resources are thrown at the problem.
What "tricks" ?
Precompiled headers sprang to mind in about half a second.
<https://en.wikipedia.org/wiki/Precompiled_header>
Andy
These are used primarily in C++, where you often have /very/ large
headers that require a significant amount of analysis. In C, this is
not remotely the same scale of problem. C headers are usually far
shorter - and far simpler to process. (In a quick test on my system, #include <stdio.h> pulled in 792 lines, while #include <iostream> took
28152 lines.)
On 21/06/2024 10:46, David Brown wrote:
On 20/06/2024 22:21, Vir Campestris wrote:
On 17/06/2024 20:29, David Brown wrote:
I do my C development with optimisations enabled, which means that
the C compiler will obey all the rules and requirements of C.
Optimisations don't change the meaning of correct code - they only
have an effect on the results of your code if you have written
incorrect code. I don't know about you, but my aim in development
is to write /correct/ code. If disabling optimisations helped in
some way, it would be due to bugs and luck.
To me disabling optimisations does one slightly useful thing
(compiles a little quicker) and one really useful one. It makes the
interactive debugger work. Optimised code confuses the debugger,
especially when it does things like reorder code, unroll loops, or
merge equivalent functions.
Of course I then test with the optimised version.
Andy
I understand your viewpoint and motivation. But my own experience is
mostly different.
First, to get it out of the way, there's the speed of compilation.
While heavy optimisation (-O3) can take noticeably longer, I never see
-O0 as being in any noticeable way faster for compilation than -O1 or
even -O2.
Absolute time or relative?
For me, optimised options with gcc always
take longer:
 C:\c>tm gcc bignum.c -shared -s -obignum.dll       # from cold
 TM: 3.85
 C:\c>tm gcc bignum.c -shared -s -obignum.dll
 TM: 0.31
 C:\c>tm gcc bignum.c -shared -s -obignum.dll -O2
 TM: 0.83
 C:\c>tm gcc bignum.c -shared -s -obignum.dll -O3
 TM: 0.93
 C:\c>dir bignum.dll
 21/06/2024 11:14           35,840 bignum.dll
On 21/06/2024 11:46, David Brown wrote:
On 20/06/2024 22:31, Vir Campestris wrote:
On 17/06/2024 14:43, David Brown wrote:
Compilation speed is important to everyone. That's why so many
tricks are used to get around the lack of speed in a big compiler,
or so many extra resources are thrown at the problem.
What "tricks" ?
Precompiled headers sprang to mind in about half a second.
<https://en.wikipedia.org/wiki/Precompiled_header>
Andy
These are used primarily in C++, where you often have /very/ large
headers that require a significant amount of analysis. In C, this is
not remotely the same scale of problem. C headers are usually far
shorter - and far simpler to process. (In a quick test on my system,
#include <stdio.h> pulled in 792 lines, while #include <iostream> took
28152 lines.)
C standard headers are nothing. From 3K to 5K lines between Windows and Linux, last time I looked. That's for all 30 headers.
(Which is why I
think they should just be included anyway.)
But library headers can be much bigger. I already gave a timing for windows.h, of 1.4 seconds. SDL2, quite a small library compared with
some, is still 50K lines, and adds 0.75 seconds compilation per module.
On 21/06/2024 15:25, bart wrote:
On 21/06/2024 11:46, David Brown wrote:
On 20/06/2024 22:31, Vir Campestris wrote:
On 17/06/2024 14:43, David Brown wrote:
Compilation speed is important to everyone. That's why so many
tricks are used to get around the lack of speed in a big compiler, >>>>>> or so many extra resources are thrown at the problem.
What "tricks" ?
Precompiled headers sprang to mind in about half a second.
<https://en.wikipedia.org/wiki/Precompiled_header>
Andy
These are used primarily in C++, where you often have /very/ large
headers that require a significant amount of analysis. In C, this is
not remotely the same scale of problem. C headers are usually far
shorter - and far simpler to process. (In a quick test on my system,
#include <stdio.h> pulled in 792 lines, while #include <iostream>
took 28152 lines.)
C standard headers are nothing. From 3K to 5K lines between Windows
and Linux, last time I looked. That's for all 30 headers.
C headers for most other libraries are usually also short, at least
compared to C++ headers.
(Which is why I think they should just be included anyway.)
That would be a terrible idea for many reasons.
But library headers can be much bigger. I already gave a timing for
windows.h, of 1.4 seconds. SDL2, quite a small library compared with
some, is still 50K lines, and adds 0.75 seconds compilation per module.
I don't know what version of SDL headers I have (it's not a library I
have used myself), but there are about 30 headers in the
/usr/include/SDL/ folder, totalling some 12K lines (after
preprocessing). Including them all in an otherwise blank C file takes
about 40-50 ms to compile - basically, noise.
Again, this is a decade old PC with spinning rust disk. A key
difference, of course, is that I am using an OS that is suitable for the task.
Malcolm's comparison function does not establish total order on
arbitrary strings, but it is both possible and likely that it
establishes total order on all sets of inputs that he cares about.
On 21/06/2024 15:25, bart wrote:
(Which is why I think they should just be included anyway.)
That would be a terrible idea for many reasons.
On 21/06/2024 12:42, bart wrote:
On 21/06/2024 10:46, David Brown wrote:
On 20/06/2024 22:21, Vir Campestris wrote:
On 17/06/2024 20:29, David Brown wrote:
I do my C development with optimisations enabled, which means that
the C compiler will obey all the rules and requirements of C.
Optimisations don't change the meaning of correct code - they only
have an effect on the results of your code if you have written
incorrect code. I don't know about you, but my aim in development
is to write /correct/ code. If disabling optimisations helped in
some way, it would be due to bugs and luck.
To me disabling optimisations does one slightly useful thing
(compiles a little quicker) and one really useful one. It makes the
interactive debugger work. Optimised code confuses the debugger,
especially when it does things like reorder code, unroll loops, or
merge equivalent functions.
Of course I then test with the optimised version.
Andy
I understand your viewpoint and motivation. But my own experience is
mostly different.
First, to get it out of the way, there's the speed of compilation.
While heavy optimisation (-O3) can take noticeably longer, I never
see -O0 as being in any noticeable way faster for compilation than
-O1 or even -O2.
Absolute time or relative?
Both.
For me, optimised options with gcc always take longer:
Of course. But I said it was not noticeable - it does not make enough difference in speed for it to be worth choosing.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll       # from cold >>   TM: 3.85
Cold build times are irrelevant to development - when you are working on
a project, all the source files and all your compiler files are in the
PC's cache.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll
  TM: 0.31
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O2
  TM: 0.83
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O3
  TM: 0.93
  C:\c>dir bignum.dll
  21/06/2024 11:14           35,840 bignum.dll
Any build time under a second is as good as instant.
I tested on a real project, not a single file. It has 158 C files and
about 220 header files. And I ran it on my old PC, without any "tricks" that you dislike so much, doing full clean re-builds. The files are actually all compiled twice, building two variants of the binary.
With -O2, it took 34.3 seconds to build. With -O1, it took 33.4
seconds. With -O0, it took 30.8 seconds.
So that is a 15% difference for full builds. In practice, of course,
full rebuilds are rarely needed, and most builds after changes to the
source are within a second or so.
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
[...]
On a C language point, I don't think the standard says anything about
sorting with non-order functions like the one above. Is an
implementation of qsort permitted to misbehave (for example by not
terminating) when the comparison function does not implement a proper
order relation?
N1570 7.22.5p4 (applies to bsearch and qsort):
"""
When the same objects (consisting of size bytes, irrespective of
their current positions in the array) are passed more than once to
the comparison function, the results shall be consistent with one
another. That is, for qsort they shall define a total ordering on
the array, and for bsearch the same object shall always compare
the same way with the key.
"""
That's a "shall" outside a constraint, so violating it results in
undefined behavior.
I think it should be clearer. What the "that is" phrase seems to
clarify in no way implies a total order, merely that the repeated
comparisons or the same elements are consistent with one another. That
the comparison function defines a total order on the elements is, to me,
a major extra constraint that should not be written as an apparent clarification to something the does not imply it: repeated calls should
be consistent with one another and, in addition, a total order should be imposed on the elements present.
Ben Bacarisse <ben@bsb.me.uk> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
[...]
On a C language point, I don't think the standard says anything about
sorting with non-order functions like the one above. Is an
implementation of qsort permitted to misbehave (for example by not
terminating) when the comparison function does not implement a proper
order relation?
N1570 7.22.5p4 (applies to bsearch and qsort):
"""
When the same objects (consisting of size bytes, irrespective of
their current positions in the array) are passed more than once to
the comparison function, the results shall be consistent with one
another. That is, for qsort they shall define a total ordering on
the array, and for bsearch the same object shall always compare
the same way with the key.
"""
That's a "shall" outside a constraint, so violating it results in
undefined behavior.
I think it should be clearer. What the "that is" phrase seems to
clarify in no way implies a total order, merely that the repeated
comparisons or the same elements are consistent with one another. That
the comparison function defines a total order on the elements is, to me,
a major extra constraint that should not be written as an apparent
clarification to something the does not imply it: repeated calls should
be consistent with one another and, in addition, a total order should be
imposed on the elements present.
I think you're misreading the first sentence.
Suppose we are in
court listening to an ongoing murder trial. Witness one comes in
and testifies that Alice left the house before Bob. Witness two
comes in (after witness one has gone) and testifies that Bob left
the house before Cathy. Witness three comes in (after the first
two have gone) and testifies that Cathy left the house before
Alice. None of the witnesses have contradicted either of the
other witnesses, but the testimonies of the three witnesses are
not consistent with one another.
Try a web search
"consistent with" definition
for more explanation.
Also, for "one another", if we say the
children in the Jones family get along with one another, we don't
mean that each child gets along with at least one of the others,
but instead mean that every child gets along with every other
child, that is, that they all get along with each other.
Whether
or not some other reading (of that problem sentence in the C
standard) is sensible, surely the reading I have suggested is a
plausible one. Do you agree? It seems clear, given how the
second sentence is phrased, that this suggested reading is what
was intended.
I don't mean to defend the quality of writing in this passage.
Certainly it would be nice if the meaning could have been stated
more plainly. But I think it's an overstatement to say that the
first sentence in no way implies a total order.
On 21/06/2024 14:34, David Brown wrote:
On 21/06/2024 12:42, bart wrote:
On 21/06/2024 10:46, David Brown wrote:
On 20/06/2024 22:21, Vir Campestris wrote:
On 17/06/2024 20:29, David Brown wrote:
I do my C development with optimisations enabled, which means that >>>>>> the C compiler will obey all the rules and requirements of C.
Optimisations don't change the meaning of correct code - they only >>>>>> have an effect on the results of your code if you have written
incorrect code. I don't know about you, but my aim in development >>>>>> is to write /correct/ code. If disabling optimisations helped in
some way, it would be due to bugs and luck.
To me disabling optimisations does one slightly useful thing
(compiles a little quicker) and one really useful one. It makes the
interactive debugger work. Optimised code confuses the debugger,
especially when it does things like reorder code, unroll loops, or
merge equivalent functions.
Of course I then test with the optimised version.
Andy
I understand your viewpoint and motivation. But my own experience
is mostly different.
First, to get it out of the way, there's the speed of compilation.
While heavy optimisation (-O3) can take noticeably longer, I never
see -O0 as being in any noticeable way faster for compilation than
-O1 or even -O2.
Absolute time or relative?
Both.
For me, optimised options with gcc always take longer:
Of course. But I said it was not noticeable - it does not make enough
difference in speed for it to be worth choosing.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll       # from cold >>>   TM: 3.85
Cold build times are irrelevant to development - when you are working
on a project, all the source files and all your compiler files are in
the PC's cache.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll
  TM: 0.31
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O2
  TM: 0.83
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O3
  TM: 0.93
  C:\c>dir bignum.dll
  21/06/2024 11:14           35,840 bignum.dll
Any build time under a second is as good as instant.
I tested on a real project, not a single file. It has 158 C files and
about 220 header files. And I ran it on my old PC, without any
"tricks" that you dislike so much, doing full clean re-builds. The
files are actually all compiled twice, building two variants of the
binary.
With -O2, it took 34.3 seconds to build. With -O1, it took 33.4
seconds. With -O0, it took 30.8 seconds.
So that is a 15% difference for full builds. In practice, of course,
full rebuilds are rarely needed, and most builds after changes to the
source are within a second or so.
Then there's something very peculiar about your codebase.
Either there's disproportionate percentage of declarations compared to executable code (like my tests with headers).
Or a big chunk of the source either contains lots of redundant code,
or
generates such code, or maybe conditional code,
that is eliminated
before it gets to the optimising stages.
On 21/06/2024 14:51, David Brown wrote:
On 21/06/2024 15:25, bart wrote:
On 21/06/2024 11:46, David Brown wrote:
On 20/06/2024 22:31, Vir Campestris wrote:
On 17/06/2024 14:43, David Brown wrote:
Compilation speed is important to everyone. That's why so many
tricks are used to get around the lack of speed in a big
compiler, or so many extra resources are thrown at the problem.
What "tricks" ?
Precompiled headers sprang to mind in about half a second.
<https://en.wikipedia.org/wiki/Precompiled_header>
Andy
These are used primarily in C++, where you often have /very/ large
headers that require a significant amount of analysis. In C, this
is not remotely the same scale of problem. C headers are usually
far shorter - and far simpler to process. (In a quick test on my
system, #include <stdio.h> pulled in 792 lines, while #include
<iostream> took 28152 lines.)
C standard headers are nothing. From 3K to 5K lines between Windows
and Linux, last time I looked. That's for all 30 headers.
C headers for most other libraries are usually also short, at least
compared to C++ headers.
(Which is why I think they should just be included anyway.)
That would be a terrible idea for many reasons.
But library headers can be much bigger. I already gave a timing for
windows.h, of 1.4 seconds. SDL2, quite a small library compared with
some, is still 50K lines, and adds 0.75 seconds compilation per module.
I don't know what version of SDL headers I have (it's not a library I
have used myself), but there are about 30 headers in the
/usr/include/SDL/ folder, totalling some 12K lines (after
preprocessing). Including them all in an otherwise blank C file takes
about 40-50 ms to compile - basically, noise.
I don't trust your figures. How many lines were there /before/
preprocessing? Since if significantly more, all that has to be processed still.
Even at 12K lines and 50ms, that gives gcc a throughput of 0.25M lines
per second, something I've never seen on any version of gcc. And if it
was 50K lines like mine (just the lines in all the SDL*.h files), then
it suggests a throughput of 1M lines per second.
Again, this is a decade old PC with spinning rust disk. A key
difference, of course, is that I am using an OS that is suitable for
the task.
I tried it under WSL too (unless that doesn't really count as a suitable
OS):
  WSL        gcc 9.4 -S  0.5 seconds to process #include "sdl.h"
  Windows 11 gcc 14.1 -S  0.7 seconds
That last is the same OS where my mcc compiler takes 0.08 seconds to
process those same SDL*.h files.
I think you've misplaced a decimal point somewhere.
On 21/06/2024 14:51, David Brown wrote:
On 21/06/2024 15:25, bart wrote:
(Which is why I think they should just be included anyway.)
That would be a terrible idea for many reasons.
Such as? It can't be compilation time, since headers ten times the size
or more apparently instantly.
One delight in using my language is that its standard library is always available. But if you don't want it, it can be disabled. With C I spend
a big chunk of my time writing include lines.
First I need stdio. Then string. Then stdlib. Then there's always ones I can't quite remember.
Or I need to debug someone's code, and it needs stdio to define
'printf', FFS. Would the world stop turning if it was just available?
I just don't believe that things defined in the headers need to be micro-managed to that extent, most of the time.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:...
Ben Bacarisse <ben@bsb.me.uk> writes:
I think it should be clearer. What the "that is" phrase seems to
clarify in no way implies a total order, merely that the repeated
comparisons or the same elements are consistent with one another. That
the comparison function defines a total order on the elements is, to me, >>> a major extra constraint that should not be written as an apparent
clarification to something the does not imply it: repeated calls should >>> be consistent with one another and, in addition, a total order should be >>> imposed on the elements present.
I think you're misreading the first sentence.
Let's hope so. That's why I said it should be clearer, not that it was wrong.
Suppose we are in
court listening to an ongoing murder trial. Witness one comes in
and testifies that Alice left the house before Bob. Witness two
comes in (after witness one has gone) and testifies that Bob left
the house before Cathy. Witness three comes in (after the first
two have gone) and testifies that Cathy left the house before
Alice. None of the witnesses have contradicted either of the
other witnesses, but the testimonies of the three witnesses are
not consistent with one another.
My (apparently incorrect) reading of the first sentence is that the consistency is only required between the results of multiple calls
between each pair. In other words, if the witnesses are repeatedly
asked, again and again, if Alice left before Bob and/or if Bob left
before Alice the results would always be consistent (with, of course,
the same required of repeatedly asking about the other pairs of people).
On 21/06/2024 20:43, bart wrote:
Even at 12K lines and 50ms, that gives gcc a throughput of 0.25M lines
per second, something I've never seen on any version of gcc. And if it
was 50K lines like mine (just the lines in all the SDL*.h files), then
it suggests a throughput of 1M lines per second.
Lines per second is a completely meaningless way to measure compiler
speed. I know you like it, but it makes no sense at all - it's like >measuring the productivity of programmers in lines per day. I expect >compilers to chew through C headers far faster than main code, whether
or not they do any optimisations.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
[...]
On a C language point, I don't think the standard says anything
about sorting with non-order functions like the one above. Is
an implementation of qsort permitted to misbehave (for example
by not terminating) when the comparison function does not
implement a proper order relation?
N1570 7.22.5p4 (applies to bsearch and qsort):
"""
When the same objects (consisting of size bytes, irrespective of
their current positions in the array) are passed more than once
to the comparison function, the results shall be consistent with
one another. That is, for qsort they shall define a total
ordering on the array, and for bsearch the same object shall
always compare the same way with the key.
"""
That's a "shall" outside a constraint, so violating it results in
undefined behavior.
I think it should be clearer. What the "that is" phrase seems to
clarify in no way implies a total order, merely that the repeated
comparisons or the same elements are consistent with one another.
That the comparison function defines a total order on the elements
is, to me, a major extra constraint that should not be written as
an apparent clarification to something the does not imply it:
repeated calls should be consistent with one another and, in
addition, a total order should be imposed on the elements present.
I think you're misreading the first sentence.
Let's hope so. That's why I said it should be clearer, not that it
was wrong.
Suppose we are in
court listening to an ongoing murder trial. Witness one comes in
and testifies that Alice left the house before Bob. Witness two
comes in (after witness one has gone) and testifies that Bob left
the house before Cathy. Witness three comes in (after the first
two have gone) and testifies that Cathy left the house before
Alice. None of the witnesses have contradicted either of the
other witnesses, but the testimonies of the three witnesses are
not consistent with one another.
My (apparently incorrect) reading of the first sentence is that
the consistency is only required between the results of multiple
calls between each pair. In other words, if the witnesses are
repeatedly asked, again and again, if Alice left before Bob and/or
if Bob left before Alice the results would always be consistent
(with, of course, the same required of repeatedly asking about the
other pairs of people).
Try a web search
"consistent with" definition
for more explanation.
Seriously?
Also, for "one another", if we say the
children in the Jones family get along with one another, we don't
mean that each child gets along with at least one of the others,
but instead mean that every child gets along with every other
child, that is, that they all get along with each other.
The sentence in question has, to my mind, already stated what the
"one another" refers to -- the multiple calls between pairs
containing the same objects. I get you think that's not the
intended meaning, but I get my reading so strongly that I struggle
to see the other.
Whether
or not some other reading (of that problem sentence in the C
standard) is sensible, surely the reading I have suggested is a
plausible one. Do you agree? It seems clear, given how the
second sentence is phrased, that this suggested reading is what
was intended.
I still can't read it the way you do. Every time I try, I find
the consistency is to be taken as applying to the results of the
multiple calls between pairs of the same objects. Nothing more.
It starts with "When the same objects". It seems so clear that
the consistency is all about the multiple calls with these same
objects. I keep trying to see your reading of it, but I can't.
I don't mean to defend the quality of writing in this passage.
Certainly it would be nice if the meaning could have been stated
more plainly. But I think it's an overstatement to say that the
first sentence in no way implies a total order.
I have a second objection that promoted that remark. If I take the (apparently) intended meaning of the first sentence, I think that "consistent" is too weak to imply even a partial order. In dog club
tonight, because of how they get on, I will ensure that Enzo is
walking behind George, that George is walking behind Benji, Benji
behind Gibson, Gibson behind Pepper and Pepper behind Enzo. In what
sense is this "ordering" not consistent? All the calls to the
comparison function are consistent with each other.
I certainly would favor improved wording that made this clearer.
In fact, simply explicitly mandating total ordering rather than
making a vague comment about consistency would probably be the
best approach.
On 21/06/2024 23:47, bart wrote:
On 21/06/2024 14:34, David Brown wrote:
On 21/06/2024 12:42, bart wrote:
On 21/06/2024 10:46, David Brown wrote:
On 20/06/2024 22:21, Vir Campestris wrote:
On 17/06/2024 20:29, David Brown wrote:
I do my C development with optimisations enabled, which meansTo me disabling optimisations does one slightly useful thing
that the C compiler will obey all the rules and requirements of
C. Optimisations don't change the meaning of correct code - they >>>>>>> only have an effect on the results of your code if you have
written incorrect code. I don't know about you, but my aim in
development is to write /correct/ code. If disabling
optimisations helped in some way, it would be due to bugs and luck. >>>>>>
(compiles a little quicker) and one really useful one. It makes
the interactive debugger work. Optimised code confuses the
debugger, especially when it does things like reorder code, unroll >>>>>> loops, or merge equivalent functions.
Of course I then test with the optimised version.
Andy
I understand your viewpoint and motivation. But my own experience
is mostly different.
First, to get it out of the way, there's the speed of compilation.
While heavy optimisation (-O3) can take noticeably longer, I never
see -O0 as being in any noticeable way faster for compilation than
-O1 or even -O2.
Absolute time or relative?
Both.
For me, optimised options with gcc always take longer:
Of course. But I said it was not noticeable - it does not make
enough difference in speed for it to be worth choosing.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll       # from cold >>>>   TM: 3.85
Cold build times are irrelevant to development - when you are working
on a project, all the source files and all your compiler files are in
the PC's cache.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll
  TM: 0.31
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O2
  TM: 0.83
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O3
  TM: 0.93
  C:\c>dir bignum.dll
  21/06/2024 11:14           35,840 bignum.dll
Any build time under a second is as good as instant.
I tested on a real project, not a single file. It has 158 C files
and about 220 header files. And I ran it on my old PC, without any
"tricks" that you dislike so much, doing full clean re-builds. The
files are actually all compiled twice, building two variants of the
binary.
With -O2, it took 34.3 seconds to build. With -O1, it took 33.4
seconds. With -O0, it took 30.8 seconds.
So that is a 15% difference for full builds. In practice, of course,
full rebuilds are rarely needed, and most builds after changes to the
source are within a second or so.
Then there's something very peculiar about your codebase.
In my experience, programs don't usually consist of a single C file. And
if they do, build time is rarely long enough to worry anyone.
I think, from the history of discussions in this group, that it is more likely that your codebases are the peculiar ones.
However, it is certainly fair to say that codebases vary a lot, as do
build procedures.
Either there's disproportionate percentage of declarations compared to
executable code (like my tests with headers).
No.
Or a big chunk of the source either contains lots of redundant code,
No.
or generates such code, or maybe conditional code,
There's a bit, but not much.
that is eliminated before it gets to the optimising stages.
To be fair here, I have a /lot/ of flags for my builds, and the only
thing I changed here was the main optimisation number. Other flags
might still have had an influence in the compiler run time, such as the warning flags. But there's a limit to how much effort I'm going to
spend playing around for a Usenet post.
 And a great many of the flags
(not the warning flags) are important for actually generating the
correct code for the correct target, so sorting out those that could be removed in order to make a completely pointless and useless
near-unoptimised build is just not worth the effort. However, changing
the main optimisation number to 0 certainly reduced the code generation
to much less efficient code - likely too slow to work for some critical aspects of the program.
On 23/06/2024 13:25, David Brown wrote:
In my experience, programs don't usually consist of a single C file.
And if they do, build time is rarely long enough to worry anyone.
I think, from the history of discussions in this group, that it is
more likely that your codebases are the peculiar ones.
I specifically excluded any of my own. I tried a variety of distinct projects, all sharing the same characteristics: that -O3 generally
doubled build time, sometimes a bit less, often a lot more.
But you seem remarkably unbothered that in your code-base, the
difference is only 15% [for -O2]. I'd be quite curious.
If that really was typical, and I was in charge of gcc, I'd seriously consider whether to bother with the -O0 and -O1 levels.
However the following timings to build TCC/lUA are typical of my
experience of gcc over 10-20 years:
  (tcc 0.10)
  -O0  2.84 seconds to build tcc.exe
  -O1  5.70
  -O2 10.78
  -O3 13.21
  (tcc 0.25)
  -O0  7.74 seconds to build lua.exe
  -O1 10.63
  -O2 14.95
  -O3 18.24
I've shown the timings from building with Tcc to give some perspective.
The proportional difference between -O3 and -O0 is indeed small compared
with that between -O0 and tcc!
Ben Bacarisse <ben@bsb.me.uk> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
[...]
On a C language point, I don't think the standard says anything
about sorting with non-order functions like the one above. Is
an implementation of qsort permitted to misbehave (for example
by not terminating) when the comparison function does not
implement a proper order relation?
N1570 7.22.5p4 (applies to bsearch and qsort):
"""
When the same objects (consisting of size bytes, irrespective of
their current positions in the array) are passed more than once
to the comparison function, the results shall be consistent with
one another. That is, for qsort they shall define a total
ordering on the array, and for bsearch the same object shall
always compare the same way with the key.
"""
That's a "shall" outside a constraint, so violating it results in
undefined behavior.
I think it should be clearer. What the "that is" phrase seems to
clarify in no way implies a total order, merely that the repeated
comparisons or the same elements are consistent with one another.
That the comparison function defines a total order on the elements
is, to me, a major extra constraint that should not be written as
an apparent clarification to something the does not imply it:
repeated calls should be consistent with one another and, in
addition, a total order should be imposed on the elements present.
I think you're misreading the first sentence.
Let's hope so. That's why I said it should be clearer, not that it
was wrong.
Suppose we are in
court listening to an ongoing murder trial. Witness one comes in
and testifies that Alice left the house before Bob. Witness two
comes in (after witness one has gone) and testifies that Bob left
the house before Cathy. Witness three comes in (after the first
two have gone) and testifies that Cathy left the house before
Alice. None of the witnesses have contradicted either of the
other witnesses, but the testimonies of the three witnesses are
not consistent with one another.
My (apparently incorrect) reading of the first sentence is that
the consistency is only required between the results of multiple
calls between each pair. In other words, if the witnesses are
repeatedly asked, again and again, if Alice left before Bob and/or
if Bob left before Alice the results would always be consistent
(with, of course, the same required of repeatedly asking about the
other pairs of people).
Let me paraphrase that. When the same pair of objects is passed
more than once to individual calls of the comparison function, the
results of those different calls shall each be consistent with
every other one of the results.
To paraphrase my reading, when some set of "same" objects is each
passed more than once to individual calls of the comparison
function, the results of all of those calls taken together shall
not imply an ordering contradiction.
Are the last two paragraphs fair restatements of our respective
readings?
Is the second paragraph plain enough so that you
would not misconstrue it if read in isolation? Or if not, can
you suggest a better phrasing?
Try a web search
"consistent with" definition
for more explanation.
Seriously?
Yes, it's a serious suggestion, and I'm sorry if it came across as condescending. I did this search myself, and learned something from
it. The important point is the "consistent with" is something of an idiomatic phrase, and it doesn't mean "equivalent to" or "the same
as". Maybe you already knew that, but I didn't, and learning it
helped me see what the quoted passage is getting at.
Also, for "one another", if we say the
children in the Jones family get along with one another, we don't
mean that each child gets along with at least one of the others,
but instead mean that every child gets along with every other
child, that is, that they all get along with each other.
The sentence in question has, to my mind, already stated what the
"one another" refers to -- the multiple calls between pairs
containing the same objects. I get you think that's not the
intended meaning, but I get my reading so strongly that I struggle
to see the other.
Yes, I got that. The incongruity between the first sentence and the
second sentence prompted me to re-examine the entire paragraph,
which is what eventually led me to my current reading.
Whether
or not some other reading (of that problem sentence in the C
standard) is sensible, surely the reading I have suggested is a
plausible one. Do you agree? It seems clear, given how the
second sentence is phrased, that this suggested reading is what
was intended.
I still can't read it the way you do. Every time I try, I find
the consistency is to be taken as applying to the results of the
multiple calls between pairs of the same objects. Nothing more.
It starts with "When the same objects". It seems so clear that
the consistency is all about the multiple calls with these same
objects. I keep trying to see your reading of it, but I can't.
Yes, the phrase "the same objects" starts one down a wrong path.
What I think is meant is that "sameness" applies to objects
individually, without regard to what the object is being compared
to. It's a tricky point because it isn't literally the same object:
what is meant is the same "logical" object, not the same physical
object. If you think of "the same objects" as meaning a set of
individual logical objects, rather than pairs of logical objects,
that might be a way to dislodge the (unfortunately all too easy
to fall into) initial impression.
I don't mean to defend the quality of writing in this passage.
Certainly it would be nice if the meaning could have been stated
more plainly. But I think it's an overstatement to say that the
first sentence in no way implies a total order.
I have a second objection that promoted that remark. If I take the
(apparently) intended meaning of the first sentence, I think that
"consistent" is too weak to imply even a partial order. In dog club
tonight, because of how they get on, I will ensure that Enzo is
walking behind George, that George is walking behind Benji, Benji
behind Gibson, Gibson behind Pepper and Pepper behind Enzo. In what
sense is this "ordering" not consistent? All the calls to the
comparison function are consistent with each other.
I understand the objection, and this is the point I was trying to
make in the paragraph about children in the Jones family. The
phrase "one another" in "the results shall be consistent with one
another" is meant to be read as saying "all the results taken
together". It is not enough that results not be contradictory taken
two at a time; considering all the results at once must not lead to
an ordering contradiction.
Hopefully this has been helpful for you. If it hasn't I'd like to
hear where the sticking points are.
James Kuyper <jameskuyper@alumni.caltech.edu> writes:
[on the requirements for qsort]
I certainly would favor improved wording that made this clearer.
In fact, simply explicitly mandating total ordering rather than
making a vague comment about consistency would probably be the
best approach.
Clearly the C standard intends to impose a weaker requirement
than that the comparison function be a total ordering.
On 23/06/2024 22:09, bart wrote:
On 23/06/2024 19:21, bart wrote:43 seconds compile time is getting to be a bit of a problem. But not for
On 23/06/2024 13:25, David Brown wrote:
In my experience, programs don't usually consist of a single C file.
And if they do, build time is rarely long enough to worry anyone.
I think, from the history of discussions in this group, that it is
more likely that your codebases are the peculiar ones.
I specifically excluded any of my own. I tried a variety of distinct
projects, all sharing the same characteristics: that -O3 generally
doubled build time, sometimes a bit less, often a lot more.
But you seem remarkably unbothered that in your code-base, the
difference is only 15% [for -O2]. I'd be quite curious.
If that really was typical, and I was in charge of gcc, I'd seriously
consider whether to bother with the -O0 and -O1 levels.
However the following timings to build TCC/lUA are typical of my
experience of gcc over 10-20 years:
   (tcc 0.10)
   -O0  2.84 seconds to build tcc.exe
   -O1  5.70
   -O2 10.78
   -O3 13.21
   (tcc 0.25)
   -O0  7.74 seconds to build lua.exe
   -O1 10.63
   -O2 14.95
   -O3 18.24
I've shown the timings from building with Tcc to give some
perspective. The proportional difference between -O3 and -O0 is
indeed small compared with that between -O0 and tcc!
I've done one more test, which is compiling 140 .c files of Seed7 to
object files (not linking). This was done under WSL and outside of a
makefile where there were a million things going on that I had no idea
about.
Results were:
  -O0  17 seconds
  -O2  36 seconds
  -O3  43 seconds
This was done with one invocation of gcc. Invoking gcc each time might
well make it slower, but a test I did along those lines was not
conclusive.
So, if the difference between O0 and O2 is so narrow for you, and it's
not the source code, nor how you invoke gcc, then there must be other
things going on.
the final build. Only for intermediate builds.
On 24/06/2024 00:52, Malcolm McLean wrote:
43 seconds compile time is getting to be a bit of a problem. But not for
the final build. Only for intermediate builds.
That isn't the issue here (it could have been 4.3 seconds vs 1.7 seconds).
David Brown was claiming there was little difference (15%, although on
the 34.3s and 30.8s timings, it is actually 11% not 15%) between
optimised and unoptimised builds, whereas I have always seen substantial >differences like 100% or more.
bart <bc@freeuk.com> writes:
On 24/06/2024 00:52, Malcolm McLean wrote:
43 seconds compile time is getting to be a bit of a problem. But not for >>> the final build. Only for intermediate builds.
That isn't the issue here (it could have been 4.3 seconds vs 1.7 seconds). >>
David Brown was claiming there was little difference (15%, although on
the 34.3s and 30.8s timings, it is actually 11% not 15%) between
optimised and unoptimised builds, whereas I have always seen substantial
differences like 100% or more.
David is likely referring to the average.
You've obviously found
an outlier. I've one outlier that compiles with -O0 in about
15 seconds, and with -O3 it takes 8 minutes. However, the
code in that file is far from optimal. The rest of the source
files in that project (20+ million lines) are more in the 10-15%
range, if that high.
I took a look at the outlier, and got rid of some unnecessary
local block declarations in a large function, removed some unnecessary #include's and cut the -O3 time in half, to just under 4
minutes. The variable tracking feature of the gnu compiler
collection seems to be the culprit here.
On 23/06/2024 13:25, David Brown wrote:
To be fair here, I have a /lot/ of flags for my builds, and the only
thing I changed here was the main optimisation number. Other flags
might still have had an influence in the compiler run time, such as
the warning flags. But there's a limit to how much effort I'm going
to spend playing around for a Usenet post.
That depends on whether your want your findings to be accurate and not misleading. ATM your figures and also your comments raise some red flags
for me.
TBF this is a problem with smart compilers, some may find some way of
caching previous results - beyond whatever the file system does - even
if you delete the relevant binaries (I think Rust or Zig did this).
 And a great many of the flags (not the warning flags) are important
for actually generating the correct code for the correct target, so
sorting out those that could be removed in order to make a completely
pointless and useless near-unoptimised build is just not worth the
effort. However, changing the main optimisation number to 0 certainly
reduced the code generation to much less efficient code - likely too
slow to work for some critical aspects of the program.
And yet, -O2 must have invoked all those dozens of optimising passes to
make that difference, all for only 15% cost?
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
[...]
On a C language point, I don't think the standard says anything
about sorting with non-order functions like the one above. Is
an implementation of qsort permitted to misbehave (for example
by not terminating) when the comparison function does not
implement a proper order relation?
N1570 7.22.5p4 (applies to bsearch and qsort):
"""
When the same objects (consisting of size bytes, irrespective of
their current positions in the array) are passed more than once
to the comparison function, the results shall be consistent with
one another. That is, for qsort they shall define a total
ordering on the array, and for bsearch the same object shall
always compare the same way with the key.
"""
That's a "shall" outside a constraint, so violating it results in
undefined behavior.
I think it should be clearer. What the "that is" phrase seems to
clarify in no way implies a total order, merely that the repeated
comparisons or the same elements are consistent with one another.
That the comparison function defines a total order on the elements
is, to me, a major extra constraint that should not be written as
an apparent clarification to something the does not imply it:
repeated calls should be consistent with one another and, in
addition, a total order should be imposed on the elements present.
I think you're misreading the first sentence.
Let's hope so. That's why I said it should be clearer, not that it
was wrong.
Suppose we are in
court listening to an ongoing murder trial. Witness one comes in
and testifies that Alice left the house before Bob. Witness two
comes in (after witness one has gone) and testifies that Bob left
the house before Cathy. Witness three comes in (after the first
two have gone) and testifies that Cathy left the house before
Alice. None of the witnesses have contradicted either of the
other witnesses, but the testimonies of the three witnesses are
not consistent with one another.
My (apparently incorrect) reading of the first sentence is that
the consistency is only required between the results of multiple
calls between each pair. In other words, if the witnesses are
repeatedly asked, again and again, if Alice left before Bob and/or
if Bob left before Alice the results would always be consistent
(with, of course, the same required of repeatedly asking about the
other pairs of people).
Let me paraphrase that. When the same pair of objects is passed
more than once to individual calls of the comparison function, the
results of those different calls shall each be consistent with
every other one of the results.
No, only with the results of the other calls that get passed the same
pair. [...]
To paraphrase my reading, when some set of "same" objects is each
passed more than once to individual calls of the comparison
function, the results of all of those calls taken together shall
not imply an ordering contradiction.
Are the last two paragraphs fair restatements of our respective
readings?
I don't think so. The first does not seem to be what I meant, and the
second begs a question: what is an ordering contradiction?
Maybe I could work out what you mean by that if I thought about it
some more, but this discussion has reminded me why I swore not to
discuss wording and interpretation on Usenet. You found the wording adequate. I didn't. I won't mind if no one ever knows exactly why
I didn't. C has managed fine with this wording for decades so there
is no practical problem. I think enough time has been spent on this discussion already, but I can sense more is likely to spent.
Is the second paragraph plain enough so that you
would not misconstrue it if read in isolation? Or if not, can
you suggest a better phrasing?
Since I don't know what an ordering contradiction is, I can't suggest
an alternative.
Try a web search
"consistent with" definition
for more explanation.
Seriously?
Yes, it's a serious suggestion, and I'm sorry if it came across as
condescending. I did this search myself, and learned something from
it. The important point is the "consistent with" is something of an
idiomatic phrase, and it doesn't mean "equivalent to" or "the same
as". Maybe you already knew that, but I didn't, and learning it
helped me see what the quoted passage is getting at.
I find that /inconsistent/ with what I've previously inferred about
your knowledge of English, but I have to take your word for it.
If you care to be less cryptic, maybe you will say what it was
about the meaning of "consistent with" that helped you see what
the text in question was getting at.
Also, for "one another", if we say the
children in the Jones family get along with one another, we don't
mean that each child gets along with at least one of the others,
but instead mean that every child gets along with every other
child, that is, that they all get along with each other.
The sentence in question has, to my mind, already stated what the
"one another" refers to -- the multiple calls between pairs
containing the same objects. I get you think that's not the
intended meaning, but I get my reading so strongly that I struggle
to see the other.
Yes, I got that. The incongruity between the first sentence and the
second sentence prompted me to re-examine the entire paragraph,
which is what eventually led me to my current reading.
Whether
or not some other reading (of that problem sentence in the C
standard) is sensible, surely the reading I have suggested is a
plausible one. Do you agree? It seems clear, given how the
second sentence is phrased, that this suggested reading is what
was intended.
I still can't read it the way you do. Every time I try, I find
the consistency is to be taken as applying to the results of the
multiple calls between pairs of the same objects. Nothing more.
It starts with "When the same objects". It seems so clear that
the consistency is all about the multiple calls with these same
objects. I keep trying to see your reading of it, but I can't.
Yes, the phrase "the same objects" starts one down a wrong path.
What I think is meant is that "sameness" applies to objects
individually, without regard to what the object is being compared
to. It's a tricky point because it isn't literally the same object:
what is meant is the same "logical" object, not the same physical
object. If you think of "the same objects" as meaning a set of
individual logical objects, rather than pairs of logical objects,
that might be a way to dislodge the (unfortunately all too easy
to fall into) initial impression.
Can you express this mathematically? I can't follow these
words at all. I am clearly getting mentally old.
I don't mean to defend the quality of writing in this passage.
Certainly it would be nice if the meaning could have been stated
more plainly. But I think it's an overstatement to say that the
first sentence in no way implies a total order.
I have a second objection that promoted that remark. If I take the
(apparently) intended meaning of the first sentence, I think that
"consistent" is too weak to imply even a partial order. In dog club
tonight, because of how they get on, I will ensure that Enzo is
walking behind George, that George is walking behind Benji, Benji
behind Gibson, Gibson behind Pepper and Pepper behind Enzo. In what
sense is this "ordering" not consistent? All the calls to the
comparison function are consistent with each other.
I understand the objection, and this is the point I was trying to
make in the paragraph about children in the Jones family. The
phrase "one another" in "the results shall be consistent with one
another" is meant to be read as saying "all the results taken
together". It is not enough that results not be contradictory taken
two at a time; considering all the results at once must not lead to
an ordering contradiction.
So you agree that the first sentence in no way implies a total order?
All the results of the dog-order comparison function, taken together,
are consistent with the circular order, which is obviously not a total
order.
I must be missing something because you don't say anything else to
indicate a change of opinion. Are you making what to me is a circular argument that consistent means consistent with a total order, not some
other ordering relationship?
Hopefully this has been helpful for you. If it hasn't I'd like to
hear where the sticking points are.
I think I am a little more confused than I was.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
James Kuyper <jameskuyper@alumni.caltech.edu> writes:
[on the requirements for qsort]
I certainly would favor improved wording that made this clearer.
In fact, simply explicitly mandating total ordering rather than
making a vague comment about consistency would probably be the
best approach.
Clearly the C standard intends to impose a weaker requirement
than that the comparison function be a total ordering.
The plot thickens. Unless, of course, you are referring to the
distinction you drew before between an ordering of all possible objects
and only those in the array.
On 24/06/2024 09:28, David Brown wrote:
On 24/06/2024 02:56, Scott Lurndal wrote:
bart <bc@freeuk.com> writes:
On 24/06/2024 00:52, Malcolm McLean wrote:
43 seconds compile time is getting to be a bit of a problem. But
not for
the final build. Only for intermediate builds.
That isn't the issue here (it could have been 4.3 seconds vs 1.7
seconds).
David Brown was claiming there was little difference (15%, although on >>>> the 34.3s and 30.8s timings, it is actually 11% not 15%) between
optimised and unoptimised builds, whereas I have always seen
substantial
differences like 100% or more.
I think the main problem is that Bart doesn't understand what "builds"
are. And he doesn't understand the relevance - or irrelevance - of
compile times while developing software, and how they relate to
/build/ times or /development/ time. I don't care how long it takes
to compile a file - I care how long the build takes.
I've been building programs for approaching half a century, and I've
been developing tools do so for most of that.
Do you really thing I don't know what a 'build' is?
On 24/06/2024 02:56, Scott Lurndal wrote:
bart <bc@freeuk.com> writes:
On 24/06/2024 00:52, Malcolm McLean wrote:
43 seconds compile time is getting to be a bit of a problem. But not
for
the final build. Only for intermediate builds.
That isn't the issue here (it could have been 4.3 seconds vs 1.7
seconds).
David Brown was claiming there was little difference (15%, although on
the 34.3s and 30.8s timings, it is actually 11% not 15%) between
optimised and unoptimised builds, whereas I have always seen substantial >>> differences like 100% or more.
I think the main problem is that Bart doesn't understand what "builds"
are. And he doesn't understand the relevance - or irrelevance - of
compile times while developing software, and how they relate to /build/
times or /development/ time. I don't care how long it takes to compile
a file - I care how long the build takes.
On 21/06/2024 14:34, David Brown wrote:
On 21/06/2024 12:42, bart wrote:
On 21/06/2024 10:46, David Brown wrote:
I understand your viewpoint and motivation. But my own
experience is mostly different.
First, to get it out of the way, there's the speed of
compilation. While heavy optimisation (-O3) can take noticeably
longer, I never see -O0 as being in any noticeable way faster for
compilation than -O1 or even -O2.
Absolute time or relative?
Both.
For me, optimised options with gcc always take longer:
Of course. But I said it was not noticeable - it does not make
enough difference in speed for it to be worth choosing.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll       # from cold
  TM: 3.85
Cold build times are irrelevant to development - when you are
working on a project, all the source files and all your compiler
files are in the PC's cache.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll
  TM: 0.31
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O2
  TM: 0.83
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O3
  TM: 0.93
  C:\c>dir bignum.dll
  21/06/2024 11:14           35,840 bignum.dll
Any build time under a second is as good as instant.
I tested on a real project, not a single file. It has 158 C files
and about 220 header files. And I ran it on my old PC, without any "tricks" that you dislike so much, doing full clean re-builds. The
files are actually all compiled twice, building two variants of the
binary.
With -O2, it took 34.3 seconds to build. With -O1, it took 33.4 seconds. With -O0, it took 30.8 seconds.
So that is a 15% difference for full builds. In practice, of
course, full rebuilds are rarely needed, and most builds after
changes to the source are within a second or so.
Then there's something very peculiar about your codebase.
On 24/06/2024 13:17, bart wrote:
On 24/06/2024 09:28, David Brown wrote:
On 24/06/2024 02:56, Scott Lurndal wrote:
bart <bc@freeuk.com> writes:
On 24/06/2024 00:52, Malcolm McLean wrote:
43 seconds compile time is getting to be a bit of a problem. But
not for
the final build. Only for intermediate builds.
That isn't the issue here (it could have been 4.3 seconds vs 1.7
seconds).
David Brown was claiming there was little difference (15%, although on >>>>> the 34.3s and 30.8s timings, it is actually 11% not 15%) between
optimised and unoptimised builds, whereas I have always seen
substantial
differences like 100% or more.
I think the main problem is that Bart doesn't understand what
"builds" are. And he doesn't understand the relevance - or
irrelevance - of compile times while developing software, and how
they relate to /build/ times or /development/ time. I don't care how
long it takes to compile a file - I care how long the build takes.
I've been building programs for approaching half a century, and I've
been developing tools do so for most of that.
Do you really thing I don't know what a 'build' is?
Given your decade (at least) old battle to misunderstand the most
commonly used build tool, yes.
On Fri, 21 Jun 2024 22:47:46 +0100
bart <bc@freeuk.com> wrote:
On 21/06/2024 14:34, David Brown wrote:
On 21/06/2024 12:42, bart wrote:
On 21/06/2024 10:46, David Brown wrote:
I understand your viewpoint and motivation. But my own
experience is mostly different.
First, to get it out of the way, there's the speed of
compilation. While heavy optimisation (-O3) can take noticeably
longer, I never see -O0 as being in any noticeable way faster for
compilation than -O1 or even -O2.
Absolute time or relative?
Both.
For me, optimised options with gcc always take longer:
Of course. But I said it was not noticeable - it does not make
enough difference in speed for it to be worth choosing.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll       # from cold
  TM: 3.85
Cold build times are irrelevant to development - when you are
working on a project, all the source files and all your compiler
files are in the PC's cache.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll
  TM: 0.31
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O2
  TM: 0.83
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O3
  TM: 0.93
  C:\c>dir bignum.dll
  21/06/2024 11:14           35,840 bignum.dll
Any build time under a second is as good as instant.
I tested on a real project, not a single file. It has 158 C files
and about 220 header files. And I ran it on my old PC, without any
"tricks" that you dislike so much, doing full clean re-builds. The
files are actually all compiled twice, building two variants of the
binary.
With -O2, it took 34.3 seconds to build. With -O1, it took 33.4
seconds. With -O0, it took 30.8 seconds.
So that is a 15% difference for full builds. In practice, of
course, full rebuilds are rarely needed, and most builds after
changes to the source are within a second or so.
Then there's something very peculiar about your codebase.
To me it looks more likely that your codebase is very unusual rather
than David's
In order to get meaningful measurements I took embedded project that
is significantly bigger than average by my standards. Here are times of
full parallel rebuild (make -j5) on relatively old computer (4-core Xeon E3-1271 v3).
Option time(s) -g time text size
-O0 13.1 13.3 631648
-Os 13.6 14.1 424016
-O1 13.5 13.7 455728
-O2 14.0 14.1 450056
-O3 14.0 14.6 525380
The difference in time between different -O settings in my measurements
is even smaller than reported by David Brown. That can be attributed to
older compiler (gcc 4.1.2). Another difference is that this compiler
works under cygwin, which is significantly slower both than native
Linux and than native Windows. That causes relatively higher make
overhead and longer link.
If I had were "native" tools then all times will be likely shorter by
few seconds and the difference between -O0 and -O3 will be close to 10%.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
James Kuyper <jameskuyper@alumni.caltech.edu> writes:
[on the requirements for qsort]
I certainly would favor improved wording that made this clearer.
In fact, simply explicitly mandating total ordering rather than
making a vague comment about consistency would probably be the
best approach.
Clearly the C standard intends to impose a weaker requirement
than that the comparison function be a total ordering.
"That is, for qsort they shall define a total ordering on the
array".
I presume you didn't intend to contradict that requirement, but
I can't figure out what you meant -- unless, as Ben suggested,
you're distinguishing between a total ordering of all possible
arguments and a total ordering of objects present in the array.
But even then, the standard explicitly imposes a total ordering.
(The requirements for bsearch might be weaker, but we're discussing
qsort.)
Can you clarify what you meant?
On 24/06/2024 14:09, Michael S wrote:
On Fri, 21 Jun 2024 22:47:46 +0100
bart <bc@freeuk.com> wrote:
On 21/06/2024 14:34, David Brown wrote:
On 21/06/2024 12:42, bart wrote:
On 21/06/2024 10:46, David Brown wrote:
I understand your viewpoint and motivation. But my own
experience is mostly different.
First, to get it out of the way, there's the speed of
compilation. While heavy optimisation (-O3) can take noticeably
longer, I never see -O0 as being in any noticeable way faster for
compilation than -O1 or even -O2.
Absolute time or relative?
Both.
For me, optimised options with gcc always take longer:
Of course. But I said it was not noticeable - it does not make
enough difference in speed for it to be worth choosing.
   C:\c>tm gcc bignum.c -shared -s -obignum.dll       # from cold
   TM: 3.85
Cold build times are irrelevant to development - when you are
working on a project, all the source files and all your compiler
files are in the PC's cache.
   C:\c>tm gcc bignum.c -shared -s -obignum.dll
   TM: 0.31
   C:\c>tm gcc bignum.c -shared -s -obignum.dll -O2
   TM: 0.83
   C:\c>tm gcc bignum.c -shared -s -obignum.dll -O3
   TM: 0.93
   C:\c>dir bignum.dll
   21/06/2024 11:14           35,840 bignum.dll
Any build time under a second is as good as instant.
I tested on a real project, not a single file. It has 158 C files
and about 220 header files. And I ran it on my old PC, without any
"tricks" that you dislike so much, doing full clean re-builds. The
files are actually all compiled twice, building two variants of the
binary.
With -O2, it took 34.3 seconds to build. With -O1, it took 33.4
seconds. With -O0, it took 30.8 seconds.
So that is a 15% difference for full builds. In practice, of
course, full rebuilds are rarely needed, and most builds after
changes to the source are within a second or so.
Then there's something very peculiar about your codebase.
To me it looks more likely that your codebase is very unusual rather
than David's
In order to get meaningful measurements I took embedded project that
is significantly bigger than average by my standards. Here are times of
full parallel rebuild (make -j5) on relatively old computer (4-core Xeon
E3-1271 v3).
Option time(s) -g time text size
-O0Â Â Â 13.1Â Â Â Â Â 13.3Â Â 631648
-Os   13.6     14.1  424016
-O1Â Â Â 13.5Â Â Â Â Â 13.7Â Â 455728
-O2Â Â Â 14.0Â Â Â Â Â 14.1Â Â 450056
-O3Â Â Â 14.0Â Â Â Â Â 14.6Â Â 525380
The difference in time between different -O settings in my measurements
is even smaller than reported by David Brown. That can be attributed to
older compiler (gcc 4.1.2). Another difference is that this compiler
works under cygwin, which is significantly slower both than native
Linux and than native Windows. That causes relatively higher make
overhead and longer link.
I don't know why Cygwin would make much difference; the native code is
still running on the same processor.
However, is there any way of isolating the compilation time (turning .c
files into either or .o files) from 'make' the linker?
Failing that, can
you compile just one module in isolation (.c to .o) with -O0 and -O2, or
is that not possible?
Those throughputs don't look that impressive for a parallel build on
what sounds like a high-spec machine.
If I had were "native" tools then all times will be likely shorter by
few seconds and the difference between -O0 and -O3 will be close to 10%.
So two people now saying that all the many dozens of extras passes and
extra analysis that gcc -O2/O3 has to do, compared with the basic
front-end work that every toy compiler needs to do and does it quickly,
only slows it down by 10%.
I really don't believe it. And you should understand that it doesn't add
up.
On 24/06/2024 14:09, Michael S wrote:
On Fri, 21 Jun 2024 22:47:46 +0100
bart <bc@freeuk.com> wrote:
On 21/06/2024 14:34, David Brown wrote:
On 21/06/2024 12:42, bart wrote:
On 21/06/2024 10:46, David Brown wrote:
I understand your viewpoint and motivation. But my own
experience is mostly different.
First, to get it out of the way, there's the speed of
compilation. While heavy optimisation (-O3) can take noticeably
longer, I never see -O0 as being in any noticeable way faster
for compilation than -O1 or even -O2.
Absolute time or relative?
Both.
For me, optimised options with gcc always take longer:
Of course. But I said it was not noticeable - it does not make
enough difference in speed for it to be worth choosing.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll       # from >>>> cold TM: 3.85
Cold build times are irrelevant to development - when you are
working on a project, all the source files and all your compiler
files are in the PC's cache.
  C:\c>tm gcc bignum.c -shared -s -obignum.dll
  TM: 0.31
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O2
  TM: 0.83
  C:\c>tm gcc bignum.c -shared -s -obignum.dll -O3
  TM: 0.93
  C:\c>dir bignum.dll
  21/06/2024 11:14           35,840 bignum.dll
Any build time under a second is as good as instant.
I tested on a real project, not a single file. It has 158 C files
and about 220 header files. And I ran it on my old PC, without
any "tricks" that you dislike so much, doing full clean
re-builds. The files are actually all compiled twice, building
two variants of the binary.
With -O2, it took 34.3 seconds to build. With -O1, it took 33.4
seconds. With -O0, it took 30.8 seconds.
So that is a 15% difference for full builds. In practice, of
course, full rebuilds are rarely needed, and most builds after
changes to the source are within a second or so.
Then there's something very peculiar about your codebase.
To me it looks more likely that your codebase is very unusual rather
than David's
In order to get meaningful measurements I took embedded project that
is significantly bigger than average by my standards. Here are
times of full parallel rebuild (make -j5) on relatively old
computer (4-core Xeon E3-1271 v3).
Option time(s) -g time text size
-O0 13.1 13.3 631648
-Os 13.6 14.1 424016
-O1 13.5 13.7 455728
-O2 14.0 14.1 450056
-O3 14.0 14.6 525380
The difference in time between different -O settings in my
measurements is even smaller than reported by David Brown. That can
be attributed to older compiler (gcc 4.1.2). Another difference is
that this compiler works under cygwin, which is significantly
slower both than native Linux and than native Windows. That causes relatively higher make overhead and longer link.
I don't know why Cygwin would make much difference; the native code
is still running on the same processor.
However, is there any way of isolating the compilation time (turning
.c files into either or .o files) from 'make' the linker? Failing
that, can you compile just one module in isolation (.c to .o) with
-O0 and -O2, or is that not possible?
Those throughputs don't look that impressive for a parallel build on
what sounds like a high-spec machine.
Your processor has a CPU-mark double that of mine, which has only two
cores, and is using one.
Building a 34-module project with .text size of 300KB, with either
gcc 10 or 14, using -O0, takes about 8 seconds, or 37KB/second.
Your figures show about 50KB/second.
You say you use gcc 4, but an
older gcc is more likely to be faster in compilation speed than a
newer one.
It does sound like something outside of gcc itself.
For the same project, on the same slow machine, Tiny C's throughput
is 1.3MB/second. While my non-C compiler, on other projects, is 5-10MB/second, still only looking at .text segments. That is 100
times faster than your timings, for generating code that is as good
as gcc's -O0.
So IT IS NOT WINDOWS ITSELF THAT IS SLOW.
If I had were "native" tools then all times will be likely shorter
by few seconds and the difference between -O0 and -O3 will be close
to 10%.
So two people now saying that all the many dozens of extras passes
and extra analysis that gcc -O2/O3 has to do, compared with the basic front-end work that every toy compiler needs to do and does it
quickly, only slows it down by 10%.
I really don't believe it. And you should understand that it doesn't
add up.
On 23/06/2024 17:47, Tim Rentsch wrote:
Yes, it's a serious suggestion, and I'm sorry if it came across as
condescending. I did this search myself, and learned something from
it. The important point is the "consistent with" is something of an
idiomatic phrase, and it doesn't mean "equivalent to" or "the same
as". Maybe you already knew that, but I didn't, and learning it
helped me see what the quoted passage is getting at.
We've established that the wife was in the house at the time when the
husband was killed. Which is consistent with her having done the
murder. But it doesn't by itself prove that she did the
murder. However had we been able to show that she was elsewhere at the
time, that would not be consistent with her having done the murder,
and so she would be dropped as a suspect.
On Mon, 24 Jun 2024 15:00:26 +0100
bart <bc@freeuk.com> wrote:
Your processor has a CPU-mark double that of mine, which has only two
cores, and is using one.
Building a 34-module project with .text size of 300KB, with either
gcc 10 or 14, using -O0, takes about 8 seconds, or 37KB/second.
But my project has much more than 34 modules. 164 modules compiled
during build + several dozens in libraries.
Your figures show about 50KB/second.
text KB/second is hardly a good measure, esp. considering that we are
talking about different architectures. Mine is Altera Nios2 - 32-bit
RISC processor very similar to MIPS. The code density for this
architecture is significantly lower than on ARMv7 or x386 and even
somewhat lower than x86-64 and ARM64. The exact ratio depends on the
project, but 15-20% would be typical.
Also, part of text are libraries that we not compiled during this build.
But I would think that your .text size also includes libraries.
I really don't believe it. And you should understand that it doesn't
add up.
I am not lying.
I recommend to try to compile your C compiler with gcc.
On 24/06/2024 16:00, bart wrote:
However, is there any way of isolating the compilation time (turning
.c files into either or .o files) from 'make' the linker?
Why would anyone want to do that? At times, it can be useful to do
partial builds, but compilation alone is not particularly useful.
Failing that, can you compile just one module in isolation (.c to .o)
with -O0 and -O2, or is that not possible?
Those throughputs don't look that impressive for a parallel build on
what sounds like a high-spec machine.
How can you possibly judge that when you have no idea how big the
project is?
If I had were "native" tools then all times will be likely shorter by
few seconds and the difference between -O0 and -O3 will be close to 10%.
So two people now saying that all the many dozens of extras passes and
extra analysis that gcc -O2/O3 has to do, compared with the basic
front-end work that every toy compiler needs to do and does it
quickly, only slows it down by 10%.
I really don't believe it. And you should understand that it doesn't
add up.
That's not what people have said.
They have said that /build/ times for /real/ projects, measured in real
time, with optimisation disabled do not give a speedup which justifies turning off optimisation and losing the features you get with a strong optimising compiler.
No one denies that "gcc -O0" is faster than "gcc -O3" for individual compiles, and that the percentage difference will vary and sometimes be large.
But that's not the point. People who do C development for a living, do
not measure the quality of their tools by the speed of compiling random
junk they found on the internet to see which compiler saves them half a second.
Factors that are important for considering a compiler can include, in no particular order and not all relevant to all developers :
* Does it support the target devices I need?
* Does it support the languages and language standards I want?
* Does it have the extensions I want to use?
* How good are its error messages at leading me to problems in the code?
* How good is its static checks and warnings?
* How efficient are the results?
* Is it compatible with the libraries and SDK's I want to use?
* Is it commonly used by others - colleagues, customers, suppliers?
* Is it supported by the suppliers of my microcontrollers, OS, etc.?
* Can I easily run it on multiple machines?
* Can I back it up and run it on systems in the future?
* Can I get hold of specific old versions of the tools? Can I
reasonably expect the tools to be available for a long time in the future?
* What are the policies for bug reporting, and bug fixing in the toolchain?
* How easy is it to examine the generated code?
* Does it play well with my IDE, such as cross-navigating between
compiler messages and source code?
* Does it have any restrictions in its use?
* How good is the documentation?
* Does it have enough flexibility to tune it to my needs and preferences
for source code checks and warnings?
* Does it have enough flexibility to tune it to my code generation needs
and preferences?
* Can I re-use the same tool for multiple projects?
* Can I use the same source and the same tool (or same family) on my
targets and for simulation on PC's?
* Is the tool mainstream and well-tested by users in practice?
* Does the same tool, or family of tools, work for different targets?
* Am I familiar with the tool, its idiosyncrasies, and its options?
* Is it common enough that I can google for questions about it?
* Does it generate the debugging information I need? Does it play well
with my debugger?
* Is the price within budget? Does it have locks, dongles, or other restrictions? Is commercial support available if I need it?
* Does it have run-time debugging tools such as sanitizers or optional
range checks?
* Does it run on the host systems I want to use?
* Does it have (or integrate with) other tools such as profilers or code coverage tools?
* What is the upgrade path and the expectation of future improvements in
new versions?
* Are there any legal requirements or ramifications from using the tool?
* Is it fast enough that it is not annoying to use with normal options
and common build automation tools, running on a host within reasonable budget?
Notice how important raw compiler speed is in the grand scheme of things?
The importance of tools is how effective they are for your use as a /developer/. Seconds saved on compile time are totally irrelevant
compared to days, weeks, months saved by tools that help find or prevent errors, or that let you write better or clearer code.
I use gcc - specifically toolchains built and released by ARM - because
that is the tool that I rate highest on these factors. If there were a similar featured clang toolchain I'd look closely at that too. And over
the years I have used many toolchains for many targets, some costing
multiple $K for the license.
Of course everyone likes faster compiles, all other things being equal.
But the other things are /not/ equal when comparing real-world
development tools with the likes of tcc or your little compiler. The
idea that anyone should reasonably expect to get paid for wasting
customer time and money with those is just laughable.
It's like being
hired to dig up a road and arriving with kid's sand spade then claiming
it is better than a mechanical digger because it is smaller and lighter.
On 24/06/2024 16:10, Michael S wrote:
But my project has much more than 34 modules. 164 modules compiled
during build + several dozens in libraries.
Does that matter? My example is a smaller project, but I'm comparing the
rate of compilation not total time.
If you want a bigger example, yesterday I posted one involving 140 .c
files, total EXE size is 5MB (don't know .text as this is ELF format).
-O2 took just over twice as long as -O0.
But I guess every single example I come up with is 'exceptional'.
Maybe
what's exceptional is that I measuring the runtime of the compiler, and
not all sorts of other junk.
On 24/06/2024 18:19, bart wrote:
For me it would be like
driving my car at walking pace all over town, even though most of my
time would be spent at various stopping places.
You still don't understand. You are telling people how fantastically
fast your car is, without realising it is just a remote-controlled toy
car. Nobody cars if your toy runs faster than a real tool - people will >still choose the real tool. And the real tools run fast enough for real >developers doing real work.
On 24/06/2024 16:10, Michael S wrote:
On Mon, 24 Jun 2024 15:00:26 +0100
bart <bc@freeuk.com> wrote:
Your processor has a CPU-mark double that of mine, which has only
two cores, and is using one.
Building a 34-module project with .text size of 300KB, with either
gcc 10 or 14, using -O0, takes about 8 seconds, or 37KB/second.
But my project has much more than 34 modules. 164 modules compiled
during build + several dozens in libraries.
Does that matter? My example is a smaller project, but I'm comparing
the rate of compilation not total time.
If you want a bigger example, yesterday I posted one involving 140 .c
files, total EXE size is 5MB (don't know .text as this is ELF format).
-O2 took just over twice as long as -O0.
But I guess every single example I come up with is 'exceptional'.
Maybe what's exceptional is that I measuring the runtime of the
compiler, and not all sorts of other junk.
You might claim that that other junk is necessary for the the build;
I'd dispute that.
Your figures show about 50KB/second.
text KB/second is hardly a good measure, esp. considering that we
are talking about different architectures. Mine is Altera Nios2 -
32-bit RISC processor very similar to MIPS. The code density for
this architecture is significantly lower than on ARMv7 or x386 and
even somewhat lower than x86-64 and ARM64. The exact ratio depends
on the project, but 15-20% would be typical.
Also, part of text are libraries that we not compiled during this
build. But I would think that your .text size also includes
libraries.
So, what is the total size of the code that is produced by the
compilation?
What is the data size?
I really don't believe it. And you should understand that it
doesn't add up.
I am not lying.
I'm not saying that. I'm disputing that -O2 adds only 10% compared to
-O0 when running only gcc.
I am pretty sure that DavidB also tells truth.
I recommend to try to compile your C compiler with gcc.
My C compiler is not written in C. I can transpile to C, but then it
would be a single large C file, which puts pressure on the optimiser:
C:\cx>mc -c cc # transpile to C
Compiling cc.m to cc.c
C:\cx>tm gcc cc.c # -O0 build
TM: 1.92
C:\cx>tm gcc cc.c -O2
TM: 9.22
It takes 380% longer compared with -O0. However the advantage is that
I now have a whole-program optimised application. But this is not
something I need to do routinely (maybe on production versions or
running benchmarks).
Most of the time I don't need the optimised code (which is only about
40% faster) and can build like this:
C:\cx>tm mm cc
Compiling cc.m to cc.exe
TM: 0.06
(If mm.exe is similarly boosted by via gcc, otherwise it takes 0.08s.)
So optimisation for this product take 150 times, or 15,000%, longer.
DB was however saying that he normally has optimisation turned on.
Well I'm not surprised if turning it off makes only 11% difference!
But he is not interested in super-fast builds such as those I work on.
Note that that 0.06 figure is for rebuilding my C compiler from
scratch (200KB .text size, 300KB EXE size.), and 1/3 of it is Windows
process overheads. Accurately measuring build-times when timings are
near zero is difficult.
bart <bc@freeuk.com> writes:
On 24/06/2024 16:10, Michael S wrote:
But my project has much more than 34 modules. 164 modules compiled
during build + several dozens in libraries.
Does that matter? My example is a smaller project, but I'm comparing the
rate of compilation not total time.
If you want a bigger example, yesterday I posted one involving 140 .c
files, total EXE size is 5MB (don't know .text as this is ELF format).
Why do you believe that the size of the executable is interesting?
Why do you think you think 5MB is unusualMS claimed that my project was smaller than his. So I found a bigger one.
if you don't know anything
about ELF?
The 'size' command will tell you the text size, although the text size
is a meaningless parameter in modern virtual memory systems which
load pages on demand.
$ file /tmp/a
/tmp/a: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=12944219f87c74b03ec19d1d693771e12416dd81, not stripped
$ size /tmp/a
text data bss dec hex filename
1257 548 4 1809 711 /tmp/a
$ ls -l /tmp/a
-rwxrwxr-x. 1 scott scott 8501 Jun 20 07:45 /tmp/a
When the average disk holds 1 TB, 5MB is not even in the noise.
-O2 took just over twice as long as -O0.
But I guess every single example I come up with is 'exceptional'.
By definition.
Maybe
what's exceptional is that I measuring the runtime of the compiler, and
not all sorts of other junk.
You seem to be measuring the wall-clock time which is influenced by
factors other than the size of the source file including other processes running during your compile.
On 24/06/2024 18:02, Scott Lurndal wrote:
bart <bc@freeuk.com> writes:
On 24/06/2024 16:10, Michael S wrote:
But my project has much more than 34 modules. 164 modules compiled
during build + several dozens in libraries.
Does that matter? My example is a smaller project, but I'm comparing the >>> rate of compilation not total time.
If you want a bigger example, yesterday I posted one involving 140 .c
files, total EXE size is 5MB (don't know .text as this is ELF format).
Why do you believe that the size of the executable is interesting?
Well, what metric IS interesting?
You seem to not care whether an executable is 10KB, 10MB, or 10GB. You
really don't think there's correspondence with build-time?
The .text was also something introduced by MS.
On 24/06/2024 16:09, David Brown wrote:
On 24/06/2024 16:00, bart wrote:
However, is there any way of isolating the compilation time (turning
.c files into either or .o files) from 'make' the linker?
Why would anyone want to do that? At times, it can be useful to do
partial builds, but compilation alone is not particularly useful.
It is useful when you are trying to establish the true cost of -O2
compared to -O0.
If including all sorts of extras (why not the time it
takes to DHL the resulting floppy to a client!) then any figures will be misleading.
Anyone reading this thread could well end up believing that applying -O2
to a compilation only makes gcc 10-15% slower.
Failing that, can you compile just one module in isolation (.c to .o)
with -O0 and -O2, or is that not possible?
Those throughputs don't look that impressive for a parallel build on
what sounds like a high-spec machine.
How can you possibly judge that when you have no idea how big the
project is?
Because the 'text' (code) size was provided?
If I had were "native" tools then all times will be likely shorter by
few seconds and the difference between -O0 and -O3 will be close to
10%.
So two people now saying that all the many dozens of extras passes
and extra analysis that gcc -O2/O3 has to do, compared with the basic
front-end work that every toy compiler needs to do and does it
quickly, only slows it down by 10%.
I really don't believe it. And you should understand that it doesn't
add up.
That's not what people have said.
They have said that /build/ times for /real/ projects, measured in
real time, with optimisation disabled do not give a speedup which
justifies turning off optimisation and losing the features you get
with a strong optimising compiler.
All the projects I tried except one give a typical speed-up of 2x or
more at -O0.
The exception was the SDL2 project (which now gives timings of 14 vs 17 seconds).
No one denies that "gcc -O0" is faster than "gcc -O3" for individual
compiles, and that the percentage difference will vary and sometimes
be large.
But that's not the point. People who do C development for a living,
do not measure the quality of their tools by the speed of compiling
random junk they found on the internet to see which compiler saves
them half a second.
Factors that are important for considering a compiler can include, in
no particular order and not all relevant to all developers :
* Does it support the target devices I need?
* Does it support the languages and language standards I want?
* Does it have the extensions I want to use?
* How good are its error messages at leading me to problems in the code?
* How good is its static checks and warnings?
* How efficient are the results?
* Is it compatible with the libraries and SDK's I want to use?
* Is it commonly used by others - colleagues, customers, suppliers?
* Is it supported by the suppliers of my microcontrollers, OS, etc.?
* Can I easily run it on multiple machines?
* Can I back it up and run it on systems in the future?
* Can I get hold of specific old versions of the tools? Can I
reasonably expect the tools to be available for a long time in the
future?
* What are the policies for bug reporting, and bug fixing in the
toolchain?
* How easy is it to examine the generated code?
* Does it play well with my IDE, such as cross-navigating between
compiler messages and source code?
* Does it have any restrictions in its use?
* How good is the documentation?
* Does it have enough flexibility to tune it to my needs and
preferences for source code checks and warnings?
* Does it have enough flexibility to tune it to my code generation
needs and preferences?
* Can I re-use the same tool for multiple projects?
* Can I use the same source and the same tool (or same family) on my
targets and for simulation on PC's?
* Is the tool mainstream and well-tested by users in practice?
* Does the same tool, or family of tools, work for different targets?
* Am I familiar with the tool, its idiosyncrasies, and its options?
* Is it common enough that I can google for questions about it?
* Does it generate the debugging information I need? Does it play
well with my debugger?
* Is the price within budget? Does it have locks, dongles, or other
restrictions? Is commercial support available if I need it?
* Does it have run-time debugging tools such as sanitizers or optional
range checks?
* Does it run on the host systems I want to use?
* Does it have (or integrate with) other tools such as profilers or
code coverage tools?
* What is the upgrade path and the expectation of future improvements
in new versions?
* Are there any legal requirements or ramifications from using the tool?
* Is it fast enough that it is not annoying to use with normal options
and common build automation tools, running on a host within reasonable
budget?
Notice how important raw compiler speed is in the grand scheme of things?
Yes, gcc ticks all the boxes. Except the last.
For me it would be like
driving my car at walking pace all over town, even though most of my
time would be spent at various stopping places.
You get around that minimising your visits, taking short-cuts, using
multiple cars each driven by different people to parallelise all the tasks.
But the cheapest car on the market that can do 30mph would fix it more easily.
You obviously have a very different view of what a compiler is for.
The importance of tools is how effective they are for your use as a
/developer/. Seconds saved on compile time are totally irrelevant
compared to days, weeks, months saved by tools that help find or
prevent errors, or that let you write better or clearer code.
For better or clearer code, try a new language. For me the biggest
problems of developing with C are the language itself. All the
industrial scale tools in the world can't fix the language.
I use gcc - specifically toolchains built and released by ARM -
because that is the tool that I rate highest on these factors. If
there were a similar featured clang toolchain I'd look closely at that
too. And over the years I have used many toolchains for many targets,
some costing multiple $K for the license.
Of course everyone likes faster compiles, all other things being
equal. But the other things are /not/ equal when comparing real-world
development tools with the likes of tcc or your little compiler. The
idea that anyone should reasonably expect to get paid for wasting
customer time and money with those is just laughable.
That's a good point. How much money has been wasted in paying
programmers by the hour to twiddle their thumbs while waiting for a
rebuild?
Perhap just once you can forget about analysing every obscure corner of
the code to quickly try out the latest change to see if it fixes that problem.
It's like being
hired to dig up a road and arriving with kid's sand spade then
claiming it is better than a mechanical digger because it is smaller
and lighter.
Have you considered that you could have a product that works like gcc,
in ticking most of those boxes, and yet could be nearly as fast as TCC?
But nobody is interested in that; customers such as you are so inured to
slow build-times, and have learnt to get around its sluggishness (and in
your case even convinced yourself that it is really quite fast), so that there simply aren't enough people complaining about it.
bart <bc@freeuk.com> writes:
On 24/06/2024 18:02, Scott Lurndal wrote:
bart <bc@freeuk.com> writes:
On 24/06/2024 16:10, Michael S wrote:
But my project has much more than 34 modules. 164 modules compiled
during build + several dozens in libraries.
Does that matter? My example is a smaller project, but I'm comparing the >>>> rate of compilation not total time.
If you want a bigger example, yesterday I posted one involving 140 .c
files, total EXE size is 5MB (don't know .text as this is ELF format).
Why do you believe that the size of the executable is interesting?
Well, what metric IS interesting?
You seem to not care whether an executable is 10KB, 10MB, or 10GB. You
really don't think there's correspondence with build-time?
No. The ELF file contains a lot of stuff that never gets
loaded into memory (symbol tables, DWARF section data, etc);
writing to the object files by the compiler is an insignificant
component of the overall compile time.
Build time is not related in any way to the size of the
ELF.
On 24/06/2024 18:15, David Brown wrote:
On my Windows machine, gcc -O0 took 0.20 seconds to build the 4-line
hello.c. As measured with clock() when executing 'system("gcc hello.c")'.
On WSL using 'time', it took 0.146 seconds 'real' time, 0.007 seconds
'user' time, and 0.051 seconds 'sys' time.
I'm not sure what these mean, or which one, or which combination, you
used to present your figures.
On 24/06/2024 18:19, bart wrote:
On 24/06/2024 16:09, David Brown wrote:
On 24/06/2024 16:00, bart wrote:
However, is there any way of isolating the compilation time (turning
.c files into either or .o files) from 'make' the linker?
Why would anyone want to do that? At times, it can be useful to do
partial builds, but compilation alone is not particularly useful.
It is useful when you are trying to establish the true cost of -O2
compared to -O0.
And the relevance of that is... what? Absolutely nothing. We've
already established that for some files, the difference is below the measurement threshold and for some (such as Scott's C++ example) it is massive.
But just to please you, and not because it has any bearing on reality, I isolated a couple of C files from my code, removed the stuff that is
specific to the target, and compiled with native gcc -O0 and -O2.
For one file (the largest C file in the project), "gcc -O0" took 0.085 seconds. "gcc -O2" took 0.134 seconds. Yes, optimising was slow - but
the time was negligible. For the other file, both compiles were 0.025 seconds - too fast to be distinguishable from noise.
Why do you think that is an appropriate way to guess the size of the project? Michael does embedded development - that's likely to be a
pretty big project with a lot of files. This is not PC compilation
where a "Hello, world" file can reach that size if statically linked.
No one cares about your figures. No one, except you, cares about /my/ figures. Sometimes people care about the build speed of /their/ code,
using /their/ choice of compiler and /their/ choice of options on
/their/ computers. Do you /really/ not understand that the timings you
get are utterly pointless to everyone else?
No one denies that "gcc -O0" is faster than "gcc -O3" for individual
compiles, and that the percentage difference will vary and sometimes
be large.
Yes, gcc ticks all the boxes. Except the last.
No, it does not tick all the boxes. The toolchains I use tick most of
them (including all the ones that I see as hard requirements), and do
better than any alternatives, but they are not perfect. They do,
however, happily pass the last one. I have yet to find a C compiler
that was not fast enough for my needs.
For me it would be like driving my car at walking pace all over town,
even though most of my time would be spent at various stopping places.
You still don't understand. You are telling people how fantastically
fast your car is, without realising it is just a remote-controlled toy
car. Nobody cars if your toy runs faster than a real tool - people will still choose the real tool. And the real tools run fast enough for real developers doing real work.
I use gcc - specifically toolchains built and released by ARM -
because that is the tool that I rate highest on these factors. If
there were a similar featured clang toolchain I'd look closely at
that too. And over the years I have used many toolchains for many
targets, some costing multiple $K for the license.
Of course everyone likes faster compiles, all other things being
equal. But the other things are /not/ equal when comparing real-world
development tools with the likes of tcc or your little compiler. The
idea that anyone should reasonably expect to get paid for wasting
customer time and money with those is just laughable.
That's a good point. How much money has been wasted in paying
programmers by the hour to twiddle their thumbs while waiting for a
rebuild?
None that I know of. Your worries about compiler speed are imaginary or self-imposed.
You /do/ realise that the only person that "suffers" from slow gcc times
is /you/ ?
Yes. There are two issues with that. First, a compiler as fast as tcc would make no practical difference at all to my development process. gcc
is more than fast enough for my needs. Secondly, there is no such tool, never has been, and I can confidently say, never will be. I want far
more from my tools than tcc can offer, and that takes more time.
If gcc was ten times slower than it is, it might get annoying sometimes,
and I'd then get a faster computer.
bart <bc@freeuk.com> writes:
On 24/06/2024 18:15, David Brown wrote:
On my Windows machine, gcc -O0 took 0.20 seconds to build the 4-line >>hello.c. As measured with clock() when executing 'system("gcc hello.c")'.
On WSL using 'time', it took 0.146 seconds 'real' time, 0.007 seconds >>'user' time, and 0.051 seconds 'sys' time.
I'm not sure what these mean, or which one, or which combination, you
used to present your figures.
This means that 0.146 minus 0.058 seconds were spent waiting for I/O.
The actually compiler CPU time was .007 seconds, the rest was
I/O.
Ben Bacarisse <ben@bsb.me.uk> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
James Kuyper <jameskuyper@alumni.caltech.edu> writes:
[on the requirements for qsort]
I certainly would favor improved wording that made this clearer.
In fact, simply explicitly mandating total ordering rather than
making a vague comment about consistency would probably be the
best approach.
Clearly the C standard intends to impose a weaker requirement
than that the comparison function be a total ordering.
The plot thickens. Unless, of course, you are referring to the
distinction you drew before between an ordering of all possible objects
and only those in the array.
Consider the following situation.
We have an array with seven elements, the integers 1 to 7,
in that order. We call qsort on the array, with a natural
comparison function that compares the integer values.
The qsort function starts with a check, and for any array
with eight elements or fewer a simple insertion sort is
done. Because 1 is less than 2, these elements stay
where they are. Because 2 is less than 3, there is only
the one comparison, and 3 stays where it is. And so on...
at each point in the sort an element is compared to the
one before it, and nothing changes. Six compares are
done to sort seven elements. Question: has the program
encountered any undefined behavior? (I expect you will
say no.)
Now consider a second situation.
We again have an array with seven elements, the integers 1
to 7, but not necessarily in order. We call the same
qsort function. This time though the argument for the
comparison function is for a function that just always
returns -1. The same sequence of events takes place as
did in the first situation: each element after the first
is compared to the one before it, and because the previous
element is deemed "less than" this element no movement
occurs and we proceed to the next element of the array.
Six compares are done to "sort" seven elements. Question:
has the program encountered any undefined behavior?
If there has been undefined behavior, which passages in
the C standard explains the difference relative to the
first situation?
If there has not been undefined behavior, what does that
say about what the requirements are for a call to qsort?
Ben Bacarisse <ben@bsb.me.uk> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
[...]
On a C language point, I don't think the standard says anything >>>>>>>> about sorting with non-order functions like the one above. Is >>>>>>>> an implementation of qsort permitted to misbehave (for example >>>>>>>> by not terminating) when the comparison function does not
implement a proper order relation?
N1570 7.22.5p4 (applies to bsearch and qsort):
"""
When the same objects (consisting of size bytes, irrespective of >>>>>>> their current positions in the array) are passed more than once
to the comparison function, the results shall be consistent with >>>>>>> one another. That is, for qsort they shall define a total
ordering on the array, and for bsearch the same object shall
always compare the same way with the key.
"""
That's a "shall" outside a constraint, so violating it results in >>>>>>> undefined behavior.
I think it should be clearer. What the "that is" phrase seems to
clarify in no way implies a total order, merely that the repeated
comparisons or the same elements are consistent with one another.
That the comparison function defines a total order on the elements >>>>>> is, to me, a major extra constraint that should not be written as
an apparent clarification to something the does not imply it:
repeated calls should be consistent with one another and, in
addition, a total order should be imposed on the elements present.
I think you're misreading the first sentence.
Let's hope so. That's why I said it should be clearer, not that it
was wrong.
Suppose we are in
court listening to an ongoing murder trial. Witness one comes in
and testifies that Alice left the house before Bob. Witness two
comes in (after witness one has gone) and testifies that Bob left
the house before Cathy. Witness three comes in (after the first
two have gone) and testifies that Cathy left the house before
Alice. None of the witnesses have contradicted either of the
other witnesses, but the testimonies of the three witnesses are
not consistent with one another.
My (apparently incorrect) reading of the first sentence is that
the consistency is only required between the results of multiple
calls between each pair. In other words, if the witnesses are
repeatedly asked, again and again, if Alice left before Bob and/or
if Bob left before Alice the results would always be consistent
(with, of course, the same required of repeatedly asking about the
other pairs of people).
Let me paraphrase that. When the same pair of objects is passed
more than once to individual calls of the comparison function, the
results of those different calls shall each be consistent with
every other one of the results.
No, only with the results of the other calls that get passed the same
pair. [...]
Sorry, my oversight. That's is what I meant. "When the same pair
of objects is passed more than once to individual calls of the
comparison function, the results of those different calls shall
each be consistent with every other one of THOSE results." The
consistency is meant to be only between results of comparisons
of the same pair. (This mistake illustrates how hard it is to
write good specifications in the C standard.)
To paraphrase my reading, when some set of "same" objects is each
passed more than once to individual calls of the comparison
function, the results of all of those calls taken together shall
not imply an ordering contradiction.
Are the last two paragraphs fair restatements of our respective
readings?
I don't think so. The first does not seem to be what I meant, and the
second begs a question: what is an ordering contradiction?
A conclusion that violates the usual mathematical rules of the
relations less than, equal to, greater than: A<B and B<C implies
A<C, A<B implies A!=B, A=B implies not A<B, A<B implies B>A, etc.
Maybe I could work out what you mean by that if I thought about it
some more, but this discussion has reminded me why I swore not to
discuss wording and interpretation on Usenet. You found the wording
adequate. I didn't. I won't mind if no one ever knows exactly why
I didn't. C has managed fine with this wording for decades so there
is no practical problem. I think enough time has been spent on this
discussion already, but I can sense more is likely to spent.
A small correction: I found the wording understandable. If the
question is about adequacy, I certainly can't give the current
wording 10 out of 10. I would like to see the specification for
qsort stated more plainly. Although, as you can see, I'm having
trouble figuring out how to do that.
Is the second paragraph plain enough so that you
would not misconstrue it if read in isolation? Or if not, can
you suggest a better phrasing?
Since I don't know what an ordering contradiction is, I can't suggest
an alternative.
Now that I have explained that phrase, I hope you will have a go
at finding a better wording.
...... The important point is the "consistent with" is something of an
idiomatic phrase, and it doesn't mean "equivalent to" or "the same
as". Maybe you already knew that, but I didn't, and learning it
helped me see what the quoted passage is getting at.
If you care to be less cryptic, maybe you will say what it was
about the meaning of "consistent with" that helped you see what
the text in question was getting at.
I think the key thing is that "consistent with" doesn't mean the
same. If we're comparing the same pair of objects over and over,
the results are either the same or they are different. It would
be odd to use "consistent with one another" if all that mattered
is whether they are all the same.
...I have a second objection that promoted that remark. If I take the
(apparently) intended meaning of the first sentence, I think that
"consistent" is too weak to imply even a partial order. In dog club
tonight, because of how they get on, I will ensure that Enzo is
walking behind George, that George is walking behind Benji, Benji
behind Gibson, Gibson behind Pepper and Pepper behind Enzo. In what
sense is this "ordering" not consistent? All the calls to the
comparison function are consistent with each other.
I understand the objection, and this is the point I was trying to
make in the paragraph about children in the Jones family. The
phrase "one another" in "the results shall be consistent with one
another" is meant to be read as saying "all the results taken
together". It is not enough that results not be contradictory taken
two at a time; considering all the results at once must not lead to
an ordering contradiction.
All the results of the dog-order comparison function, taken together,
are consistent with the circular order, which is obviously not a total
order.
If A<B, B<C, C<D, D<E, and E<A, we can infer from the transitivity
of the "less than" relation that A<A. But A<A can never be true, so
this set of comparison results is no good.
So I guess what we have
discovered is that "consistent with one another" is intended to mean
"obeys the usual mathematical rules for ordering relations".
It occurs to me now to say that "consistent with" is meant to
include logical inference.
That distinction is a key difference
between "consistent" and "consistent with" (at least as the two
terms might be understood). The combination of: one, the results
of the comparison function are seen as corresponding to an ordering
relation;
and two, that "consistent with one another" includes
logical inferences considering all of the results together; is what
allows us to conclude that the results define a total order.
I'm sorry if any of the above sounds like it's just stating the
obvious. I'm strugging trying to find a way to explain what to
me seems straightforward.
bart <bc@freeuk.com> writes:
On 24/06/2024 18:02, Scott Lurndal wrote:
bart <bc@freeuk.com> writes:
On 24/06/2024 16:10, Michael S wrote:
But my project has much more than 34 modules. 164 modules
compiled during build + several dozens in libraries.
Does that matter? My example is a smaller project, but I'm
comparing the rate of compilation not total time.
If you want a bigger example, yesterday I posted one involving
140 .c files, total EXE size is 5MB (don't know .text as this is
ELF format).
Why do you believe that the size of the executable is interesting?
Well, what metric IS interesting?
You seem to not care whether an executable is 10KB, 10MB, or 10GB.
You really don't think there's correspondence with build-time?
No. The ELF file contains a lot of stuff that never gets
loaded into memory (symbol tables, DWARF section data, etc);
writing to the object files by the compiler is an insignificant
component of the overall compile time.
Build time is not related in any way to the size of the
ELF.
Disk space is cheap and plentiful.
The .text was also something introduced by MS.
I don't understand this comment. .text predates any MS
compiler by more than a decade.
On 24/06/2024 18:15, David Brown wrote:
On 24/06/2024 18:19, bart wrote:
On 24/06/2024 16:09, David Brown wrote:
On 24/06/2024 16:00, bart wrote:
No one cares about your figures. No one, except you, cares about /my/
figures. Sometimes people care about the build speed of /their/ code,
using /their/ choice of compiler and /their/ choice of options on
/their/ computers. Do you /really/ not understand that the timings
you get are utterly pointless to everyone else?
Obviously /you/ don't care about fast build systems.
It's perfectly
alright for 90% of the time to build a project to be spent executing auto-conf scripts.
Some people also cared enough about linkers to develop a new generation
of linker (maybe 'gold', maybe something even newer) that is supposed to
be 5 times the speed of 'ld'.
No one denies that "gcc -O0" is faster than "gcc -O3" for individual
compiles, and that the percentage difference will vary and sometimes
be large.
Yes, gcc ticks all the boxes. Except the last.
No, it does not tick all the boxes. The toolchains I use tick most of
them (including all the ones that I see as hard requirements), and do
better than any alternatives, but they are not perfect. They do,
however, happily pass the last one. I have yet to find a C compiler
that was not fast enough for my needs.
For me it would be like driving my car at walking pace all over town,
even though most of my time would be spent at various stopping places.
You still don't understand. You are telling people how fantastically
fast your car is, without realising it is just a remote-controlled toy
car. Nobody cars if your toy runs faster than a real tool - people
will still choose the real tool. And the real tools run fast enough
for real developers doing real work.
You're wrong. My 'car' would do the equivalent job of driving around
town. Unless someone /wanted/ a vehicle that was more like a 40-tonne
truck.
Let's go back a few weeks
None that I know of. Your worries about compiler speed are imaginary
or self-imposed.
So cartoons like https://xkcd.com/303/ have no basis in fact? It's just
made up?
You /do/ realise that the only person that "suffers" from slow gcc times is /you/ ?
Forums abound with horror stories. Here are quotes from just one thread:
------------------
Well a build used to take 6 or 7 minutes, and that's a long time for my little attention span. I'd always get distracted waiting for builds and
waste even more time.
In short, if a developer is waiting on a build to run for one hour and
doing nothing in that timeframe, the business is still spending $75 on average for that developer’s time—and potentially losing out on time
that developer could be focusing on building more code.
I worked on a system where only linking the binary took 40-50 minutes.
For some technical reasons there was no dynamic linking - only static -
so you had to go through that delay for the slightest change.
This is why my computer and build server have an 11900k. Builds went
from 45 minutes to 15.
This is the reason I stopped being a Java developer and embraced JS.
Even the 1-3 minutes of build time was a big hit for me because it was
just enough time for me to get distracted by something else and then the
next thing you know, you have wasted 30 mins.
------------------
Maybe you should tell these guys how it's done!
If gcc was ten times slower than it is, it might get annoying
sometimes, and I'd then get a faster computer.
The wrong approach.
(I'm not suggesting Michael change for this project - for serious
embedded work, repeatable builds and consistency of toolchains is
generally far more important than build times. But I presume he'll
use newer and better tools for new projects.)
On Mon, 24 Jun 2024 17:09:25 +0200
David Brown <david.brown@hesbynett.no> wrote:
(I'm not suggesting Michael change for this project - for serious
embedded work, repeatable builds and consistency of toolchains is
generally far more important than build times. But I presume he'll
use newer and better tools for new projects.)
It is not that simple.
Tools are supplied by Altera (more recently called Intel, but gossips
are that will be called Altera again really soon now).
Of course, I can build gcc compiler and binutils to native exe myself,
but then it wouldn't be supported. And I'd still will be forced to run
these native tools from cygwin shell because of compatibility with
other vendor-supplied tools.
Altera/Intel-supplied Nios2 SDK on Windows up to 2018 was based on
cygwin. 2019-2022 it is based on WSL. 2023 and later it is "deprecated"
in theory and removed in practice, both on Windows and on Linux, in
favor of "Nios-V" which is a name for Intel-supplied RISC-V core.
I have a weak hope that if Altera become more independent then the last
step will be reversed, but by now it's what we have.
As you can see, at no point they supported msys/msys2-based tools any
other "native" Windows form of tools.
So practical choice Intel/Altera give is between cygwin and WSL. WSL is
not usable in our working environment. That leaves cygwin.
And it's not that bad.
Yes, cygwin shell is inconvenient, but not unusable. Yes, cygwin is
slower. But project that I presented is among our biggest and still a
full rebuild takes only ~15 seconds on rather old hardware. During development full rebuilds are very rare. More typical build on more
typical project is 2-3 seconds. For me, it's slightly inconvenient, but tolerable. For few other co-workers it's not even inconvenient. I know
few people for whom it would be quite unnerving, but luckily non of
them is currently doing Nios2 sw development.
So, your presumption is wrong. I am going to start new project that
among other things involves Nios2 software and I planning to start it
with cygwin-based build tools. A little newer version of tools (gcc 5.2 instead of 4.1, newer binutils 2.25 etc) but otherwise almost identical
to 11 y.o. SDK that was used to gather numbers in post above.
At no point in all this does anyone care in the slightest about the
speed of your little toys or of the cute little tcc. tcc might be ideal
for the half-dozen people in the world who think C scripts are a good
idea, and it had its place in a time when "live Linux" systems were
booted from floppies, but that's about it.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
James Kuyper <jameskuyper@alumni.caltech.edu> writes:
[on the requirements for qsort]
I certainly would favor improved wording that made this clearer.
In fact, simply explicitly mandating total ordering rather than
making a vague comment about consistency would probably be the
best approach.
Clearly the C standard intends to impose a weaker requirement
than that the comparison function be a total ordering.
The plot thickens. Unless, of course, you are referring to the
distinction you drew before between an ordering of all possible objects
and only those in the array.
Consider the following situation.
We have an array with seven elements, the integers 1 to 7,
in that order. We call qsort on the array, with a natural
comparison function that compares the integer values.
The qsort function starts with a check, and for any array
with eight elements or fewer a simple insertion sort is
done. Because 1 is less than 2, these elements stay
where they are. Because 2 is less than 3, there is only
the one comparison, and 3 stays where it is. And so on...
at each point in the sort an element is compared to the
one before it, and nothing changes. Six compares are
done to sort seven elements. Question: has the program
encountered any undefined behavior? (I expect you will
say no.)
Now consider a second situation.
We again have an array with seven elements, the integers 1
to 7, but not necessarily in order. We call the same
qsort function. This time though the argument for the
comparison function is for a function that just always
returns -1. The same sequence of events takes place as
did in the first situation: each element after the first
is compared to the one before it, and because the previous
element is deemed "less than" this element no movement
occurs and we proceed to the next element of the array.
Six compares are done to "sort" seven elements. Question:
has the program encountered any undefined behavior?
If there has been undefined behavior, which passages in
the C standard explains the difference relative to the
first situation?
If there has not been undefined behavior, what does that
say about what the requirements are for a call to qsort?
So you are pointing out that only the comparisons made have to be
"consistent with one another"? BTW, your function that returns -1 is
just the total extension of my partial "dog order" function.
On Mon, 24 Jun 2024 18:10:20 GMT
scott@slp53.sl.home (Scott Lurndal) wrote:
Well, what metric IS interesting?
You seem to not care whether an executable is 10KB, 10MB, or 10GB.
You really don't think there's correspondence with build-time?
No. The ELF file contains a lot of stuff that never gets
loaded into memory (symbol tables, DWARF section data, etc);
writing to the object files by the compiler is an insignificant
component of the overall compile time.
Build time is not related in any way to the size of the
ELF.
That's why in my original post in this sub-thread, in order to give
a feeling of the size of compiler's job I gave the size of text
segment rather than size of the elf.
The size of text segment is, of course, not a good measure of
compiler's job, esp. when we are trying to compare compile jobs for
different target architectures, but it is less bad than any alternative >measure [that is not too hard to gather] that I can think of.
If you can think about anything better, please tell us.
Michael S <already5chosen@yahoo.com> writes:
On Mon, 24 Jun 2024 18:10:20 GMT
scott@slp53.sl.home (Scott Lurndal) wrote:
Well, what metric IS interesting?
You seem to not care whether an executable is 10KB, 10MB, or 10GB.
You really don't think there's correspondence with build-time?
No. The ELF file contains a lot of stuff that never gets
loaded into memory (symbol tables, DWARF section data, etc);
writing to the object files by the compiler is an insignificant
component of the overall compile time.
Build time is not related in any way to the size of the
ELF.
That's why in my original post in this sub-thread, in order to give
a feeling of the size of compiler's job I gave the size of text
segment rather than size of the elf.
The size of text segment is, of course, not a good measure of
compiler's job, esp. when we are trying to compare compile jobs for
different target architectures, but it is less bad than any alternative
measure [that is not too hard to gather] that I can think of.
If you can think about anything better, please tell us.
Does the compiled code meet functional and performance specifications?
That's the only criteria that matters. Size of the executable
and compilation speed are basically irrelevent metrics in my
experience.
On 25/06/2024 14:48, Scott Lurndal wrote:
That's why in my original post in this sub-thread, in order to give
a feeling of the size of compiler's job I gave the size of text
segment rather than size of the elf.
The size of text segment is, of course, not a good measure of
compiler's job, esp. when we are trying to compare compile jobs for
different target architectures, but it is less bad than any alternative
measure [that is not too hard to gather] that I can think of.
If you can think about anything better, please tell us.
Does the compiled code meet functional and performance specifications?
That's the only criteria that matters. Size of the executable
and compilation speed are basically irrelevent metrics in my
experience.
If apparently anything goes,
and you don't care how slow a tool is or
how big its output, how do you detect unnecessary bloat?
How do you detect gratuitous use of machine resources?
BTW since you and DB are both keen on products like Python,
On 25/06/2024 09:19, David Brown wrote:
At no point in all this does anyone care in the slightest about the
speed of your little toys or of the cute little tcc. tcc might be
ideal for the half-dozen people in the world who think C scripts are a
good idea, and it had its place in a time when "live Linux" systems
were booted from floppies, but that's about it.
Yet, projects like mine, and like tcc, show what is possible: just how
fast should it take to turn lower level code into machine code.
Since as I said I don't see much difference in such a task compared with doing the same with assembly, or translating textual data into binary.
So, if someone is using a tool (and perhaps language) that takes 1, 2 or
3 magnitudes longer for the same scale of task, then the trade-offs had better be worthwhile.
And it shouldn't be because the developers of the tool are lousy at
writing performant code. Or they don't care. Or they expect customers to
just use faster and bigger hardware.
You think it is all totally pointless? Then fuck you.
bart <bc@freeuk.com> writes:
On 25/06/2024 14:48, Scott Lurndal wrote:
That's why in my original post in this sub-thread, in order to give
a feeling of the size of compiler's job I gave the size of text
segment rather than size of the elf.
The size of text segment is, of course, not a good measure of
compiler's job, esp. when we are trying to compare compile jobs for
different target architectures, but it is less bad than any alternative >>>> measure [that is not too hard to gather] that I can think of.
If you can think about anything better, please tell us.
Does the compiled code meet functional and performance specifications?
That's the only criteria that matters. Size of the executable
and compilation speed are basically irrelevent metrics in my
experience.
If apparently anything goes,
I never said that.
and you don't care how slow a tool is or
I never said that.
how big its output, how do you detect unnecessary bloat?
I don't write programs with unnecessary bloat.
How do you detect gratuitous use of machine resources?
I write code that doesn't gratuitously use machine resources.
BTW since you and DB are both keen on products like Python,
I have never posted anything about python here, that I recall.
I use it very infrequently.
On 25/06/2024 17:08, Scott Lurndal wrote:
bart <bc@freeuk.com> writes:
On 25/06/2024 14:48, Scott Lurndal wrote:
That's why in my original post in this sub-thread, in order to give
a feeling of the size of compiler's job I gave the size of text
segment rather than size of the elf.
The size of text segment is, of course, not a good measure of
compiler's job, esp. when we are trying to compare compile jobs for
different target architectures, but it is less bad than any
alternative
measure [that is not too hard to gather] that I can think of.
If you can think about anything better, please tell us.
Does the compiled code meet functional and performance specifications? >>>>
That's the only criteria that matters. Size of the executable
and compilation speed are basically irrelevent metrics in my
experience.
If apparently anything goes,
I never said that.
and you don't care how slow a tool is or
I never said that.
how big its output, how do you detect unnecessary bloat?
I don't write programs with unnecessary bloat.
How do you detect gratuitous use of machine resources?
I write code that doesn't gratuitously use machine resources.
These answers apply to me tool.
BTW since you and DB are both keen on products like Python,
I have never posted anything about python here, that I recall.
I use it very infrequently.
I /do/ use Python. I use it when it is an appropriate language to use,
 which is very different circumstances from when I use C (or C++). Different tools for different tasks.
On 25/06/2024 09:19, David Brown wrote:
At no point in all this does anyone care in the slightest about the
speed of your little toys or of the cute little tcc. tcc might be
ideal for the half-dozen people in the world who think C scripts are a
good idea, and it had its place in a time when "live Linux" systems
were booted from floppies, but that's about it.
Yet, projects like mine, and like tcc, show what is possible: just how
fast should it take to turn lower level code into machine code.
On 25/06/2024 16:12, David Brown wrote:
I use it very infrequently.
(It seemed to be a big part of that 8Mloc project of yours)
And yet neither of you are interested in answering my question, which
was why its simplistic bytecode compiler is acceptable in this scenario,
but would be considered useless if applied to C code.
On 25/06/2024 17:59, bart wrote:
On 25/06/2024 16:12, David Brown wrote:
On 25/06/2024 17:08, Scott Lurndal wrote:
BTW since you and DB are both keen on products like Python,
I have never posted anything about python here, that I recall.
I use it very infrequently.
(It seemed to be a big part of that 8Mloc project of yours)
I got the impression that it was just for some scripting and automation.
On 25/06/2024 16:12, David Brown wrote:
On 25/06/2024 17:08, Scott Lurndal wrote:
BTW since you and DB are both keen on products like Python,
I have never posted anything about python here, that I recall.
I use it very infrequently.
(It seemed to be a big part of that 8Mloc project of yours)
I /do/ use Python. I use it when it is an appropriate language to
use, Â Â which is very different circumstances from when I use C (or
C++). Different tools for different tasks.
And yet neither of you are interested in answering my question, which
was why its simplistic bytecode compiler is acceptable in this scenario,
but would be considered useless if applied to C code.
On 6/25/2024 7:18 AM, bart wrote:
On 25/06/2024 09:19, David Brown wrote:
At no point in all this does anyone care in the slightest about the
speed of your little toys or of the cute little tcc. tcc might be
ideal for the half-dozen people in the world who think C scripts are
a good idea, and it had its place in a time when "live Linux" systems
were booted from floppies, but that's about it.
Yet, projects like mine, and like tcc, show what is possible: just how
fast should it take to turn lower level code into machine code.
Can you use tcc to generate assembly from a .c source file?
similar to:
$ gcc -S sourcefile.c
On 25/06/2024 17:52, DFS wrote:
On 6/25/2024 7:18 AM, bart wrote:
On 25/06/2024 09:19, David Brown wrote:
At no point in all this does anyone care in the slightest about the
speed of your little toys or of the cute little tcc. tcc might be
ideal for the half-dozen people in the world who think C scripts are
a good idea, and it had its place in a time when "live Linux"
systems were booted from floppies, but that's about it.
Yet, projects like mine, and like tcc, show what is possible: just
how fast should it take to turn lower level code into machine code.
Can you use tcc to generate assembly from a .c source file?
similar to:
$ gcc -S sourcefile.c
I don't think that's an option with tcc.
gcc works by generating intermediate assembly anyway, and the -S option exposes it.
Generally it depends on compiler. Mine has it for example.
Do you think the developers of gcc don't care?
Or they are just bad at writing code?
Do you know how laughable that is? It is not
/quite/ as bad as your usual paranoia that the developers behind C,
gcc, Linux, make, and countless other things you don't understand
created them just to annoy you personally.
On 25/06/2024 17:59, bart wrote:
On 25/06/2024 16:12, David Brown wrote:
On 25/06/2024 17:08, Scott Lurndal wrote:
BTW since you and DB are both keen on products like Python,
I have never posted anything about python here, that I recall.
I use it very infrequently.
(It seemed to be a big part of that 8Mloc project of yours)
I got the impression that it was just for some scripting and
automation. I'm sure if Python were not available, he could happily
have used Perl, or Lua, or Tcl. I know that's the case for the
Python code I often have for build automation.
(/I/ have other code for PC and server programs that are in Python,
and I don't know of any other languages that would suit my needs and
wants better there. That's why I chose Python. But I don't remember
Scott talking about such code in Python.)
On 6/25/2024 3:39 PM, bart wrote:
On 25/06/2024 17:52, DFS wrote:
On 6/25/2024 7:18 AM, bart wrote:
On 25/06/2024 09:19, David Brown wrote:
At no point in all this does anyone care in the slightest about the
speed of your little toys or of the cute little tcc. tcc might be
ideal for the half-dozen people in the world who think C scripts
are a good idea, and it had its place in a time when "live Linux"
systems were booted from floppies, but that's about it.
Yet, projects like mine, and like tcc, show what is possible: just
how fast should it take to turn lower level code into machine code.
Can you use tcc to generate assembly from a .c source file?
similar to:
$ gcc -S sourcefile.c
I don't think that's an option with tcc.
It's not listed in the tcc help anyway.
gcc works by generating intermediate assembly anyway, and the -S
option exposes it.
Generally it depends on compiler. Mine has it for example.
Cool.
If you don't mind, what assembly code does your compiler generate for
this C code:
bart <bc@freeuk.com> writes:
[...]
You think it is all totally pointless? Then fuck you.[...]
Let's keep things civil.
DFS <nospam@dfs.com> writes:
[...]
Can you use tcc to generate assembly from a .c source file?
similar to:
$ gcc -S sourcefile.c
No, tcc has no such option.
I was able to get an assembly listing by running `tcc -c sourcefile.c` followed by `objdump -d sourcefile.o`.
On Tue, 25 Jun 2024 19:51:31 +0200
David Brown <david.brown@hesbynett.no> wrote:
On 25/06/2024 17:59, bart wrote:
On 25/06/2024 16:12, David Brown wrote:
On 25/06/2024 17:08, Scott Lurndal wrote:
BTW since you and DB are both keen on products like Python,
I have never posted anything about python here, that I recall.
I use it very infrequently.
(It seemed to be a big part of that 8Mloc project of yours)
I got the impression that it was just for some scripting and
automation. I'm sure if Python were not available, he could happily
have used Perl, or Lua, or Tcl. I know that's the case for the
Python code I often have for build automation.
I have hard time imagining that anybody could happily use TCL instead
of Python.
(/I/ have other code for PC and server programs that are in Python,
and I don't know of any other languages that would suit my needs and
wants better there. That's why I chose Python. But I don't remember
Scott talking about such code in Python.)
For just about anything apart from availably of [mostly free] 3rd-party libraries and/or of ready-made modules, Ruby is as good or better than Python. But Python was lucky to reach critical mass first. By now,
Python has better docs as well, but that's relatively recent
development.
On Tue, 25 Jun 2024 17:08:42 +0200
David Brown <david.brown@hesbynett.no> wrote:
Do you think the developers of gcc don't care?
That's about right. At least for C, they don't.
Most likely the same applies even stronger to Fortran.
For C++ they would love to not care, but then their compiler would
become unusable. So they have to care, but probably very sorry about it.
However bigger reason is not lack of care, but the style of their
development process. It's best described as a patchwork.
On 25/06/2024 21:04, Keith Thompson wrote:
bart <bc@freeuk.com> writes:
[...]
You think it is all totally pointless? Then fuck you.[...]
Let's keep things civil.
He felt provoked. So it is I who need to think more, be more respectful
and be less provocative in my wording. My apologies to Bart, and to the group for frustrating him that much.
Then people have different concepts of what a 'build' is.
My definition is a full translation from source code to executable
binary. That, I have never had any trouble with for my own projects, and
have never had to hang about for it either, because I define and control
the process (and most often write the necessary tools too, AND design
the language involved to that end).
I understand your viewpoint and motivation. But my own experience is
mostly different.
First, to get it out of the way, there's the speed of compilation. While heavy optimisation (-O3) can take noticeably longer, I never see -O0 as
being in any noticeable way faster for compilation than -O1 or even
-O2. (I'm implicitly using gcc options here, but it's mostly applicable
to any serious compiler I have used.) Frankly, if your individual C compiles during development are taking too long, you are doing something wrong. Maybe you are using far too big files, or trying to do too much
in one part - split the code into manageable sections and possibly into libraries, and it will be far easier to understand, write and test.
Maybe you are not using appropriate build tools. Maybe you are using a
host computer that is long outdated or grossly underpowered.
There are exceptions. Clearly some languages - like C++ - are more demanding of compilers than others. And if you are using whole-program
or link-time optimisation, compilation and build time is more of an
issue - but of course these only make sense with strong optimisation.
Secondly, there is the static error analysis. While it is possible to
do this using additional tools, your first friend is your compiler and
its warnings. (Even with additional tools, you'll want compiler
warnings enabled.)Â You always want to find your errors as early as
possible - from your editor/IDE, your compiler, your linker, your
additional linters, your automatic tests, your manual tests, your beta
tests, your end user complaints. The earlier in this chain you find the issue, the faster, easier and cheaper it is to fix things. And
compilers do a better job at static error checking with strong
optimisations enabled, because they do more code analysis.
Thirdly, optimisation allows you to write your code with more focus on clarity, flexibility and maintainability, relying on the compiler for
the donkey work of efficiency details. If you want efficient results
(and that doesn't always matter - but if it doesn't, then C is probably
not the best choice of language in the first place) and you also want to write good quality source code, optimisation is a must.
Now to your point about debugging. It is not uncommon for me to use debuggers, including single-stepping, breakpoints, monitoring variables, modifying data via the debugger, and so on. It is common practice in embedded development. I also regularly examine the generated assembly,
and debug at that level. If I am doing a lot of debugging on a section
of code, I generally use -O1 rather than -O0 - precisely because it is
far /easier/ to understand the generated code. Typically it is hard to
see what is going on in the assembly because it is swamped by stack
accesses or code that would be far simpler when optimised. (That goes
back to the focus on source code clarity and flexibility rather than micro-managing for run-time efficiency without optimisation.)
Some specific optimisation options can make a big difference to
debugging, and can be worth disabling, such as "-fno-inline" or "-fno-top-reorder", and heavily optimised code can be hard to follow in
a debugger. But disabling optimisation entirely can often, IME, make
things harder.
Temporarily changing optimisation flags for all or part of the code
while chasing particular bugs is a useful tool, however.
On 25/06/2024 16:12, David Brown wrote:...
I /do/ use Python. I use it when it is an appropriate language to use,
which is very different circumstances from when I use C (or
C++). Different tools for different tasks.
And yet neither of you are interested in answering my question, which was
why its simplistic bytecode compiler is acceptable in this scenario, but would be considered useless if applied to C code.
On 21/06/2024 10:46, David Brown wrote:
Or maybe I have a really big code base. (My last project at work was
I understand your viewpoint and motivation. But my own experience is
mostly different.
First, to get it out of the way, there's the speed of compilation.
While heavy optimisation (-O3) can take noticeably longer, I never see
-O0 as being in any noticeable way faster for compilation than -O1 or
even -O2. (I'm implicitly using gcc options here, but it's mostly
applicable to any serious compiler I have used.)Â Frankly, if your
individual C compiles during development are taking too long, you are
doing something wrong. Maybe you are using far too big files, or
trying to do too much in one part - split the code into manageable
sections and possibly into libraries, and it will be far easier to
understand, write and test. Maybe you are not using appropriate build
tools. Maybe you are using a host computer that is long outdated or
grossly underpowered.
using a distributed compilation system across all our workstations)
I must admit I haven't tried O1 or O2. I'll give it a go.
There are exceptions. Clearly some languages - like C++ - are moreIn recent years most of my code has ben C++.
demanding of compilers than others. And if you are using
whole-program or link-time optimisation, compilation and build time is
more of an issue - but of course these only make sense with strong
optimisation.
Now I'm retired I'm not writing much serious code anyway - for some
reason I don't seem to have the time for any voluntary projects, and all
I do is a little hackery. If it's really small I'll do it in a spreadsheet.
Agreed. The cost of maintenance is often overlooked, and correct code is
Secondly, there is the static error analysis. While it is possible to
do this using additional tools, your first friend is your compiler and
its warnings. (Even with additional tools, you'll want compiler
warnings enabled.)Â You always want to find your errors as early as
possible - from your editor/IDE, your compiler, your linker, your
additional linters, your automatic tests, your manual tests, your beta
tests, your end user complaints. The earlier in this chain you find
the issue, the faster, easier and cheaper it is to fix things. And
compilers do a better job at static error checking with strong
optimisations enabled, because they do more code analysis.
Thirdly, optimisation allows you to write your code with more focus on
clarity, flexibility and maintainability, relying on the compiler for
the donkey work of efficiency details. If you want efficient results
(and that doesn't always matter - but if it doesn't, then C is
probably not the best choice of language in the first place) and you
also want to write good quality source code, optimisation is a must.
more useful than faster code.
Now to your point about debugging. It is not uncommon for me to use
debuggers, including single-stepping, breakpoints, monitoring
variables, modifying data via the debugger, and so on. It is common
practice in embedded development. I also regularly examine the
generated assembly, and debug at that level. If I am doing a lot of
debugging on a section of code, I generally use -O1 rather than -O0 -
precisely because it is far /easier/ to understand the generated
code. Typically it is hard to see what is going on in the assembly
because it is swamped by stack accesses or code that would be far
simpler when optimised. (That goes back to the focus on source code
clarity and flexibility rather than micro-managing for run-time
efficiency without optimisation.)
Some specific optimisation options can make a big difference to
debugging, and can be worth disabling, such as "-fno-inline" or
"-fno-top-reorder", and heavily optimised code can be hard to follow
in a debugger. But disabling optimisation entirely can often, IME,
make things harder.
Temporarily changing optimisation flags for all or part of the code
while chasing particular bugs is a useful tool, however.
I'll play with the settings.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
[...]
On a C language point, I don't think the standard says
anything about sorting with non-order functions like the one >>>>>>>>> above. Is an implementation of qsort permitted to misbehave >>>>>>>>> (for example by not terminating) when the comparison
function does not implement a proper order relation?
N1570 7.22.5p4 (applies to bsearch and qsort):
"""
When the same objects (consisting of size bytes, irrespective
of their current positions in the array) are passed more than
once to the comparison function, the results shall be
consistent with one another. That is, for qsort they shall
define a total ordering on the array, and for bsearch the
same object shall always compare the same way with the key.
"""
That's a "shall" outside a constraint, so violating it
results in undefined behavior.
I think it should be clearer. What the "that is" phrase seems
to clarify in no way implies a total order, merely that the
repeated comparisons or the same elements are consistent with
one another. That the comparison function defines a total
order on the elements is, to me, a major extra constraint that
should not be written as an apparent clarification to
something the does not imply it: repeated calls should be
consistent with one another and, in addition, a total order
should be imposed on the elements present.
I think you're misreading the first sentence.
Let's hope so. That's why I said it should be clearer, not that
it was wrong.
Suppose we are in court listening to an ongoing murder trial.
Witness one comes in and testifies that Alice left the house
before Bob. Witness two comes in (after witness one has gone)
and testifies that Bob left the house before Cathy. Witness
three comes in (after the first two have gone) and testifies
that Cathy left the house before Alice. None of the witnesses
have contradicted either of the other witnesses, but the
testimonies of the three witnesses are not consistent with one
another.
My (apparently incorrect) reading of the first sentence is that
the consistency is only required between the results of multiple
calls between each pair. In other words, if the witnesses are
repeatedly asked, again and again, if Alice left before Bob
and/or if Bob left before Alice the results would always be
consistent (with, of course, the same required of repeatedly
asking about the other pairs of people).
Let me paraphrase that. When the same pair of objects is passed
more than once to individual calls of the comparison function,
the results of those different calls shall each be consistent
with every other one of the results.
No, only with the results of the other calls that get passed the
same pair. [...]
Sorry, my oversight. That's is what I meant. "When the same pair
of objects is passed more than once to individual calls of the
comparison function, the results of those different calls shall
each be consistent with every other one of THOSE results." The
consistency is meant to be only between results of comparisons of
the same pair. (This mistake illustrates how hard it is to write
good specifications in the C standard.)
To paraphrase my reading, when some set of "same" objects is each
passed more than once to individual calls of the comparison
function, the results of all of those calls taken together shall
not imply an ordering contradiction.
Are the last two paragraphs fair restatements of our respective
readings?
I don't think so. The first does not seem to be what I meant, and
the second begs a question: what is an ordering contradiction?
A conclusion that violates the usual mathematical rules of the
relations less than, equal to, greater than: A<B and B<C implies
A<C, A<B implies A!=B, A=B implies not A<B, A<B implies B>A, etc.
Maybe I could work out what you mean by that if I thought about it
some more, but this discussion has reminded me why I swore not to
discuss wording and interpretation on Usenet. You found the
wording adequate. I didn't. I won't mind if no one ever knows
exactly why I didn't. C has managed fine with this wording for
decades so there is no practical problem. I think enough time has
been spent on this discussion already, but I can sense more is
likely to spent.
A small correction: I found the wording understandable. If the
question is about adequacy, I certainly can't give the current
wording 10 out of 10. I would like to see the specification for
qsort stated more plainly. Although, as you can see, I'm having
trouble figuring out how to do that.
Is the second paragraph plain enough so that you would not
misconstrue it if read in isolation? Or if not, can you suggest
a better phrasing?
Since I don't know what an ordering contradiction is, I can't
suggest an alternative.
Now that I have explained that phrase, I hope you will have a go
at finding a better wording.
I would not introduce your new term, "an ordering contradiction",
since it still leaves exactly what kind of order vague.
You interpret "consistent" as "consistent with a total order"
so I'd use that phrase:
"when some set of 'same' objects is each passed more than once
to individual calls of the comparison function, the results of
all of those calls taken together shall be consistent with a
total order"
Presumably you came to interpret "consistent with one another" as
implying a total order rather because of the sentence that follows
("That is, for qsort they shall define a total ordering on the
array").
I could not do that because I was interpreting the text about
multiple calls differently.
... The important point is the "consistent with" is something of
an idiomatic phrase, and it doesn't mean "equivalent to" or "the
same as". Maybe you already knew that, but I didn't, and
learning it helped me see what the quoted passage is getting at.
...
If you care to be less cryptic, maybe you will say what it was
about the meaning of "consistent with" that helped you see what
the text in question was getting at.
I think the key thing is that "consistent with" doesn't mean the
same. If we're comparing the same pair of objects over and over,
the results are either the same or they are different. It would
be odd to use "consistent with one another" if all that mattered
is whether they are all the same.
I never thought they were the same. The trouble is that (a)
different results imply the same order (e.g. -1 and -34 all mean
<) and (b) the (old) wording does not say that the objects are
passed in the same order and the result of cmp(a, b) can't be the
same as cmp(b, a) but they can be consistent. This makes
"consistent with one another" a perfectly reasonable thing to say
even in my limited view of what results are being talked about.
...
I have a second objection that promoted that remark. If I take
the (apparently) intended meaning of the first sentence, I think
that "consistent" is too weak to imply even a partial order. In
dog club tonight, because of how they get on, I will ensure that
Enzo is walking behind George, that George is walking behind
Benji, Benji behind Gibson, Gibson behind Pepper and Pepper
behind Enzo. In what sense is this "ordering" not consistent?
All the calls to the comparison function are consistent with
each other.
I understand the objection, and this is the point I was trying to
make in the paragraph about children in the Jones family. The
phrase "one another" in "the results shall be consistent with one
another" is meant to be read as saying "all the results taken
together". It is not enough that results not be contradictory
taken two at a time; considering all the results at once must
not lead to an ordering contradiction.
...
All the results of the dog-order comparison function, taken
together, are consistent with the circular order, which is
obviously not a total order.
If A<B, B<C, C<D, D<E, and E<A, we can infer from the transitivity
of the "less than" relation that A<A. But A<A can never be true,
so this set of comparison results is no good.
[Technical aside. The relation should be seen as <=. not <. You
can't conclude that I intended A < A from the informal
presentation -- no dog can be behind itself. However, this does
not alter your argument in any significant way.]
So I guess what we have discovered is that "consistent with one
another" is intended to mean "obeys the usual mathematical rules
for ordering relations".
I would say this is backwards. You are assuming the usual rules
where I gave an order that is not at all usual with the purpose of
showing that some sets of comparisons between pairs can be
"consistent with one another" when the ordering is very peculiar.
On a more mathematical note, imagine that the text was describing
a topological sort function. Is there anything in your reading of
the first sentence that would make it inappropriate? If not, that "consistent with one another" can't imply a total order.
...
It occurs to me now to say that "consistent with" is meant to
include logical inference.
Sure.
That distinction is a key difference between "consistent" and
"consistent with" (at least as the two terms might be understood).
The combination of: one, the results of the comparison function
are seen as corresponding to an ordering relation;
But, according to you, only some ordering relations.
and two, that "consistent with one another" includes logical
inferences considering all of the results together; is what
allows us to conclude that the results define a total order.
Could the sentence in question be used in the description of a
topological sort based (rather unusually) on a partial order?
Ben Bacarisse <ben@bsb.me.uk> writes:
(I am lazily keeping everything so I don't have to
think about what to exclude. I have changed some
white space but otherwise it's all here.)
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Ben Bacarisse <ben@bsb.me.uk> writes:
(I am lazily keeping everything so I don't have to
think about what to exclude. I have changed some
white space but otherwise it's all here.)
And I have lazily removed it all because I need to call it a day.
I am grateful for you very patient replies and I hope you will not be disappointed if I don't reply in detail to you latest. I think I
understand your position (though I would not want to try to summarise
it) and I think you understand how I was initially reading the text.
bart <bc@freeuk.com> writes:
On 25/06/2024 16:12, David Brown wrote:...
I /do/ use Python. I use it when it is an appropriate language to use, >>>  which is very different circumstances from when I use C (or
C++). Different tools for different tasks.
And yet neither of you are interested in answering my question, which was
why its simplistic bytecode compiler is acceptable in this scenario, but
would be considered useless if applied to C code.
You throw out a lot of these sorts of question, by which I mean
questions that you either /do/ know the answers to or which you /should/
know the answers to.
If a software engineering student asked me this sort of "challenge"
question it would immediately become homework: come up with at least two scenarios in which a simplistic C bytecode compiler would be an
unacceptable tool to use, and two in which Python with a trivial
bytecode compiler would be an acceptable tool to use. In each case
explain why. Anyone who could not would get marked down on the course.
On 26/06/2024 13:15, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 25/06/2024 16:12, David Brown wrote:...
I /do/ use Python. I use it when it is an appropriate language to use, >>>>   which is very different circumstances from when I use C (or
C++). Different tools for different tasks.
And yet neither of you are interested in answering my question, which
was
why its simplistic bytecode compiler is acceptable in this scenario, but >>> would be considered useless if applied to C code.
You throw out a lot of these sorts of question, by which I mean
questions that you either /do/ know the answers to or which you /should/
know the answers to.
If a software engineering student asked me this sort of "challenge"
question it would immediately become homework: come up with at least two
scenarios in which a simplistic C bytecode compiler would be an
unacceptable tool to use, and two in which Python with a trivial
bytecode compiler would be an acceptable tool to use. In each case
explain why. Anyone who could not would get marked down on the course.
I'm not sure what you're implying here.
Some here are consistently saying that any compiler whose internal
processes are not at the scale or depth that you find in 'professional', 'industrial scale' products like gcc, clang, icc, is not worth bothering
with and is basically a useless toy.
And yet those same people are happy that such a straightforward
compiler, which does less error-checking than Tiny C, is used within the dynamic scripting languages they employ.
It just seemed to me to be blind prejudice.
They were also unwilling to answer questions about whether, given a
simpler task of translating initialisation data such as long sequences
of integer constants, or strings, they'd be willing to entrust it to
such a 'toy' compiler or even a dedicated tool. Since here there is no analysis to be done nor any optimisation.
Assuming the answer is No, it must be the bigger, much slower product,
then it sounds like irrational hatred.
So, what would your students say?
On 26/06/2024 13:15, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 25/06/2024 16:12, David Brown wrote:...
I /do/ use Python. I use it when it is an appropriate language
to use, which is very different circumstances from when I use C
(or C++). Different tools for different tasks.
And yet neither of you are interested in answering my question,
which was why its simplistic bytecode compiler is acceptable in
this scenario, but would be considered useless if applied to C
code.
You throw out a lot of these sorts of question, by which I mean
questions that you either /do/ know the answers to or which you
/should/ know the answers to.
If a software engineering student asked me this sort of "challenge" question it would immediately become homework: come up with at
least two scenarios in which a simplistic C bytecode compiler would
be an unacceptable tool to use, and two in which Python with a
trivial bytecode compiler would be an acceptable tool to use. In
each case explain why. Anyone who could not would get marked down
on the course.
I'm not sure what you're implying here.
Some here are consistently saying that any compiler whose internal
processes are not at the scale or depth that you find in
'professional', 'industrial scale' products like gcc, clang, icc, is
not worth bothering with and is basically a useless toy.
And yet those same people are happy that such a straightforward
compiler, which does less error-checking than Tiny C, is used within
the dynamic scripting languages they employ.
It just seemed to me to be blind prejudice.
They were also unwilling to answer questions about whether, given a
simpler task of translating initialisation data such as long
sequences of integer constants, or strings, they'd be willing to
entrust it to such a 'toy' compiler or even a dedicated tool. Since
here there is no analysis to be done nor any optimisation.
Assuming the answer is No, it must be the bigger, much slower
product, then it sounds like irrational hatred.
So, what would your students say?
On Thu, 27 Jun 2024 12:16:14 +0100
bart <bc@freeuk.com> wrote:
On 26/06/2024 13:15, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 25/06/2024 16:12, David Brown wrote:...
I /do/ use Python. I use it when it is an appropriate language
to use, which is very different circumstances from when I use C
(or C++). Different tools for different tasks.
And yet neither of you are interested in answering my question,
which was why its simplistic bytecode compiler is acceptable in
this scenario, but would be considered useless if applied to C
code.
You throw out a lot of these sorts of question, by which I mean
questions that you either /do/ know the answers to or which you
/should/ know the answers to.
If a software engineering student asked me this sort of "challenge"
question it would immediately become homework: come up with at
least two scenarios in which a simplistic C bytecode compiler would
be an unacceptable tool to use, and two in which Python with a
trivial bytecode compiler would be an acceptable tool to use. In
each case explain why. Anyone who could not would get marked down
on the course.
I'm not sure what you're implying here.
Some here are consistently saying that any compiler whose internal
processes are not at the scale or depth that you find in
'professional', 'industrial scale' products like gcc, clang, icc, is
not worth bothering with and is basically a useless toy.
And yet those same people are happy that such a straightforward
compiler, which does less error-checking than Tiny C, is used within
the dynamic scripting languages they employ.
It just seemed to me to be blind prejudice.
The difference is that in dynamically typed scripting language like
python only most blatant syntactic error can be caught during initial compilation. The rest is caught in runtime.
On the other hand, C language provides significant amount of static info
that enables quite useful compile-time analysis. A lot more of mistakes
or 'likely mistakes' can be found not just in theory, but in practice.
There are language that provide more static info than C, e.g. Ada. I
fully expect that, other thing being equal, Ada compiler would be
slower than C compiler.
And then there exist one language that provides ALOT more static info
than C. I think, you can name it yourself, it happens to be the most
hyped programming language of our times. Not by chance, compiler for
this language is VERY slow.
Somehow, I tend to agree with other posters that say that you likely
know all that quite well, but pretend to not know for sake of arguments.
At no point in all this does anyone care in the slightest about thespeed of your little toys or of the cute little tcc. tcc might be ideal
They were also unwilling to answer questions about whether, given a
simpler task of translating initialisation data such as long
sequences of integer constants, or strings, they'd be willing to
entrust it to such a 'toy' compiler or even a dedicated tool. Since
here there is no analysis to be done nor any optimisation.
Assuming the answer is No, it must be the bigger, much slower
product, then it sounds like irrational hatred.
In my practice the answer is 'No' not because of 'hatred'. The
situations like those do not happen often enough to justify hassle of
using more than one compile for the same language in the same project.
On 27/06/2024 13:16, bart wrote:
And yet those same people are happy that such a straightforward
compiler, which does less error-checking than Tiny C, is used within
the dynamic scripting languages they employ.
I would expect Ben's students to understand the difference between a low level language aimed at systems programming and high efficiency
binaries, and a high-level language aimed at ease of development, convenience, and simplifying coding by avoiding manual resource
management.
I'd expect that from you too. Since you seem ignorant of these things,
I explained them to you. If you won't listen, or even try to think a little, then I can't help you learn.
It just seemed to me to be blind prejudice.
They were also unwilling to answer questions about whether, given a
simpler task of translating initialisation data such as long sequences
of integer constants, or strings, they'd be willing to entrust it to
such a 'toy' compiler or even a dedicated tool. Since here there is no
analysis to be done nor any optimisation.
I don't think I bothered answering that one because it is clearly a
pointless question.
answering your questions is a waste of time.
Assuming the answer is No, it must be the bigger, much slower product,
then it sounds like irrational hatred.
So, what would your students say?
Maybe if they read your posts, they would think you are projecting. You have consistently shown an irrational hatred and blind prejudice to C,
gcc, IDEs, make,
Linux,
and indeed every programming language that is
not your own invention, every compiler that is not your own or tcc,
every editor, linter, build automation system, and other software
development tool, and every OS except Windows. I don't quite know how
tcc and Windows escaped your obsessive "not invented here" syndrome.
Like most developers, I try to use the best tool for the job
I have no "irrational hatred" of tcc - it is simply incapable (in a
great many ways) of doing the job I need from a compiler, and for the
jobs it /can/ do it is in no way better than the tools I already need
and have.
On 27/06/2024 13:31, David Brown wrote:
On 27/06/2024 13:16, bart wrote:
I do dislike brace-syntax, 0-based indexing, and case-sensitivity. Those
are common characteristics.
Like most developers, I try to use the best tool for the job
Sure, you're a user, you don't get involved in devising new languages or creating tools, you have to use existed, trusted products. But you let
that get in the way of your views with a low tolerance for anything
different or that seems amateurish or pointless.
Over a decade ago I started looking at whole-program compilers which, if
I was more into optimising, would be lend themselves easily to
whole-program optimisation.
But while you will dismiss my own efforts out of hand, you do at least appreciate the benefits of 'LTO' (which I consider a third rate version
of what I do, and considerably more complex).
I have no "irrational hatred" of tcc - it is simply incapable (in a
great many ways) of doing the job I need from a compiler, and for the
jobs it /can/ do it is in no way better than the tools I already need
and have.
This is what I mean about you being incapable of being objective. You
dissed the whole idea of tcc for everyone. Whereas what you mean is that
it wouldn't benefit /you/ at all.
I can understand that: if you have a dozen slow components of some
elaborate process, replacing one with a faster one would make little difference.
My view is different: I already have /half/ a dozen /fast/ components,
then replacing just one with a slow product like 'gcc' makes a very noticeable difference.
On 26/06/2024 13:15, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 25/06/2024 16:12, David Brown wrote:
...
I /do/ use Python. I use it when it is an appropriate language to use, >>>> which is very different circumstances from when I use C (or
C++). Different tools for different tasks.
And yet neither of you are interested in answering my question, which was >>> why its simplistic bytecode compiler is acceptable in this scenario, but >>> would be considered useless if applied to C code.
You throw out a lot of these sorts of question, by which I mean
questions that you either /do/ know the answers to or which you /should/
know the answers to.
If a software engineering student asked me this sort of "challenge"
question it would immediately become homework: come up with at least two
scenarios in which a simplistic C bytecode compiler would be an
unacceptable tool to use, and two in which Python with a trivial
bytecode compiler would be an acceptable tool to use. In each case
explain why. Anyone who could not would get marked down on the course.
I'm not sure what you're implying here.
Some here are consistently saying that any compiler whose internal
processes are not at the scale or depth that you find in
professional', 'industrial scale' products like gcc, clang, icc, is
not worth bothering with and is basically a useless toy.
On 27/06/2024 18:28, bart wrote:
On 27/06/2024 13:31, David Brown wrote:
On 27/06/2024 13:16, bart wrote:
I'm snipping a lot, because answering it will not get us anywhere except
more frustrated.
I do dislike brace-syntax, 0-based indexing, and case-sensitivity.
Those are common characteristics.
I can fully appreciate preferences and opinions - likes and dislikes.
It's the continued determination to fight things that is irrational and incomprehensible. I happen to like these three things. But if I am programming in Python (with indentation rather than braces), Lua (with 1-based indexing) or Pascal (case insensitive), I shrug my shoulders and carry on. I don't go to comp.lang.python, or comp.lang.lua and rant and rave about how terrible the language is and how my own tools are vastly better than anything else.
Like most developers, I try to use the best tool for the job
Sure, you're a user, you don't get involved in devising new languages
or creating tools, you have to use existed, trusted products. But you
let that get in the way of your views with a low tolerance for
anything different or that seems amateurish or pointless.
That makes /no/ sense at all.
First, I am as capable as you or anyone else at finding things in C or
any other language that I think are not as good as they could have been,
or poor design decisions. The fact that I am a user, not an
implementer, is irrelevant - programming languages are made for the
users, and the effort needed to implement them is of minor concern.
Over a decade ago I started looking at whole-program compilers which,
if I was more into optimising, would be lend themselves easily to
whole-program optimisation.
But while you will dismiss my own efforts out of hand, you do at least
appreciate the benefits of 'LTO' (which I consider a third rate
version of what I do, and considerably more complex).
To be clear - as I have stated /many/ times, I appreciate the effort
needed to make your tools, and the achievement of making them. What I dispute is your insistence that your tools are /better/ than mainstream tools.
I have no "irrational hatred" of tcc - it is simply incapable (in a
great many ways) of doing the job I need from a compiler, and for the
jobs it /can/ do it is in no way better than the tools I already need
and have.
This is what I mean about you being incapable of being objective. You
dissed the whole idea of tcc for everyone. Whereas what you mean is
that it wouldn't benefit /you/ at all.
Much of what I say is clearly marked as being about /my/ uses. But yes,
I sometimes say that things that I believe apply to most people. I've
yet to hear of anything, from you or anyone else, to change my thoughts
on these things.
I can understand that: if you have a dozen slow components of some
elaborate process, replacing one with a faster one would make little
difference.
My view is different: I already have /half/ a dozen /fast/ components,
then replacing just one with a slow product like 'gcc' makes a very
noticeable difference.
No one doubts that gcc is slower than tcc. That is primarily because it does vastly more, and is a vastly more useful tool. And for most C compiles, gcc (even gcc -O2) is more than fast enough.
And it is free,
and easily available on common systems. Therefore there is no benefit
to using tcc except in very niche cases.
On 26/06/2024 13:15, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 25/06/2024 16:12, David Brown wrote:...
You throw out a lot of these sorts of question, by which I meanI /do/ use Python. I use it when it is an appropriate language to use, >>>> which is very different circumstances from when I use C (or
C++). Different tools for different tasks.
And yet neither of you are interested in answering my question, which was >>> why its simplistic bytecode compiler is acceptable in this scenario, but >>> would be considered useless if applied to C code.
questions that you either /do/ know the answers to or which you /should/
know the answers to.
If a software engineering student asked me this sort of "challenge"
question it would immediately become homework: come up with at least two
scenarios in which a simplistic C bytecode compiler would be an
unacceptable tool to use, and two in which Python with a trivial
bytecode compiler would be an acceptable tool to use. In each case
explain why. Anyone who could not would get marked down on the course.
I'm not sure what you're implying here.
bart <bc@freeuk.com> writes:
On 26/06/2024 13:15, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 25/06/2024 16:12, David Brown wrote:...
You throw out a lot of these sorts of question, by which I meanI /do/ use Python. I use it when it is an appropriate language to use, >>>>>  which is very different circumstances from when I use C (or
C++). Different tools for different tasks.
And yet neither of you are interested in answering my question, which was >>>> why its simplistic bytecode compiler is acceptable in this scenario, but >>>> would be considered useless if applied to C code.
questions that you either /do/ know the answers to or which you /should/ >>> know the answers to.
If a software engineering student asked me this sort of "challenge"
question it would immediately become homework: come up with at least two >>> scenarios in which a simplistic C bytecode compiler would be an
unacceptable tool to use, and two in which Python with a trivial
bytecode compiler would be an acceptable tool to use. In each case
explain why. Anyone who could not would get marked down on the course.
I'm not sure what you're implying here.
If you are not sure what I'm saying (and you think it worth finding out)
then you could ask some questions /about what I said/. I was trying to
avoid implying anything, so please consider only what I actually said. However, I can't easily explain it if you don't say what parts you
didn't follow.
The basics are simple: you asked a question. I think you aught to be
able to answer it yourself. Can you answer your own question and
explain why those different kinds of tool might be appropriate in
certain scenarios? If you now follow what I'm saying but can't answer
your own question, can you say why you can't?
On 27/06/2024 21:23, Tim Rentsch wrote:
After taking care of all that the build did manage to produce an
executable, which appears to have run successfully.
After doing a trial run with the produced executable, I looked at
the tcc man page. As best I can tell, tcc simply silently
ignores the -fPIC option.
I think that it tries to be a drop-in replacement for gcc, so supports
some of its options, even if they don't do anything. Like -O3.
Position-independent code seems to be a recent thing with gcc tools. My
tools didn't support it either, until a year ago when I found out about
ASLR.
For most, PIC isn't a necessity.
bart <bc@freeuk.com> writes:
On 26/06/2024 13:15, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 25/06/2024 16:12, David Brown wrote:
...
I /do/ use Python. I use it when it is an appropriate language to use, >>>>> which is very different circumstances from when I use C (or
C++). Different tools for different tasks.
And yet neither of you are interested in answering my question, which was >>>> why its simplistic bytecode compiler is acceptable in this scenario, but >>>> would be considered useless if applied to C code.
You throw out a lot of these sorts of question, by which I mean
questions that you either /do/ know the answers to or which you /should/ >>> know the answers to.
If a software engineering student asked me this sort of "challenge"
question it would immediately become homework: come up with at least two >>> scenarios in which a simplistic C bytecode compiler would be an
unacceptable tool to use, and two in which Python with a trivial
bytecode compiler would be an acceptable tool to use. In each case
explain why. Anyone who could not would get marked down on the course.
I'm not sure what you're implying here.
Some here are consistently saying that any compiler whose internal
processes are not at the scale or depth that you find in
professional', 'industrial scale' products like gcc, clang, icc, is
not worth bothering with and is basically a useless toy.
After reading the above I decided to try tcc. I used tcc for
the first time earlier today.
First I tried using tcc for my most recent project. That
didn't go anywhere, because that project relies on C11,
and tcc doesn't support C11.
Next I tried using tcc on a small part of my larger current
project. That test involves compiling one .c file to produce a
.o file, and linking with several other .o files to produce an
executable, and running the executable. The .c file being
compiled uses C99 and doesn't need C11.
The first thing that came up is tcc doesn't support all of
C99. There are some C99 features that tcc just doesn't
understand.
In this case the infringements were minor so I
edited the source to work around the missing features.
The second thing to come up is some language incompatibilities.
There are language features that tcc understands, sort of,
but implements them in a way that didn't work with my source
code. To be fair, a case could be made that what tcc does
conforms to the C standard. However, the code I had before
works fine with gcc
again the changes needed were minor so I edited the source
to work around the problem.
The third thing to come up was the link step. Compiling the
one .c file with tcc -- and there are three other .o files
produced using gcc -- implicated the link step, which needed
to be done with tcc to avoid some undefined symbols. That
kind of surprised me; I'm used to being able to mix gcc
object files and clang object files with no difficulty,
so having the link step fail caught me off guard.
After taking care of all that the build did manage to produce an
executable, which appears to have run successfully.
After doing a trial run with the produced executable, I looked at
the tcc man page. As best I can tell, tcc simply silently
ignores the -fPIC option.
the tcc man page says.) That project absolutely relies on -fPIC,
so if tcc doesn't support it that's a deal breaker.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
[...]
After reading the above I decided to try tcc. I used tcc for
the first time earlier today.
[...]
You probably used tcc 0.9.27, the most recent release, from 2017.
Development has continued, with a git repo at
git://repo.or.cz/tinycc.git
The master branch hasn't gone past 9.9.27, but the "mob" branch has been updated as recently as 2024-03-22. It builds in just a few seconds on
my system. The same version is available on godbot.org as "TCC (trunk)".
I haven't paid much attention to what's actually been implemented post-0.9.27. See the included Changelog if you're curious. The one
thing I've noticed is that the "mob" version implements the C99 rule
that falling off the end of main does an implicit "return 0;",
admittedly a minor point.
I'm not suggesting you should build tcc from source and repeat the
experiment (I suspect it wouldn't make much difference), but it's there
if you're so inclined.
On 27/06/2024 21:23, Tim Rentsch wrote:
bart <bc@freeuk.com> writes:
On 26/06/2024 13:15, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:I'm not sure what you're implying here.
On 25/06/2024 16:12, David Brown wrote:
...
I /do/ use Python. I use it when it is an appropriate language to use, >>>>>> which is very different circumstances from when I use C (or
C++). Different tools for different tasks.
And yet neither of you are interested in answering my question, which was >>>>> why its simplistic bytecode compiler is acceptable in this scenario, but >>>>> would be considered useless if applied to C code.
You throw out a lot of these sorts of question, by which I mean
questions that you either /do/ know the answers to or which you /should/ >>>> know the answers to.
If a software engineering student asked me this sort of "challenge"
question it would immediately become homework: come up with at least two >>>> scenarios in which a simplistic C bytecode compiler would be an
unacceptable tool to use, and two in which Python with a trivial
bytecode compiler would be an acceptable tool to use. In each case
explain why. Anyone who could not would get marked down on the course. >>>
Some here are consistently saying that any compiler whose internal
processes are not at the scale or depth that you find in
professional', 'industrial scale' products like gcc, clang, icc, is
not worth bothering with and is basically a useless toy.
After reading the above I decided to try tcc. I used tcc for
the first time earlier today.
First I tried using tcc for my most recent project. That
didn't go anywhere, because that project relies on C11,
and tcc doesn't support C11.
Next I tried using tcc on a small part of my larger current
project. That test involves compiling one .c file to produce a
.o file, and linking with several other .o files to produce an
executable, and running the executable. The .c file being
compiled uses C99 and doesn't need C11.
The first thing that came up is tcc doesn't support all of
C99. There are some C99 features that tcc just doesn't
understand.
Which ones? I thought its C99 support was far more complete than
mine.
In this case the infringements were minor so I
edited the source to work around the missing features.
The second thing to come up is some language incompatibilities.
There are language features that tcc understands, sort of,
but implements them in a way that didn't work with my source
code. To be fair, a case could be made that what tcc does
conforms to the C standard. However, the code I had before
works fine with gcc
People develop sofware using compilers like gcc, and will naturally do whatever it takes to make them work with that tool. They might
inadvertently use extensions.
After doing a trial run with the produced executable, I looked at
the tcc man page. As best I can tell, tcc simply silently
ignores the -fPIC option.
I think that it tries to be a drop-in replacement for gcc, so supports
some of its options, even if they don't do anything. Like -O3.
Position-independent code seems to be a recent thing with gcc
tools. My tools didn't support it either, until a year ago when I
found out about ASLR.
For most, PIC isn't a necessity. But tcc supports shared libraries,
and some kinds of relocation, if not full PIC, are necessary.
bart <bc@freeuk.com> writes:
On 27/06/2024 21:23, Tim Rentsch wrote:
After taking care of all that the build did manage to produce an
executable, which appears to have run successfully.
After doing a trial run with the produced executable, I looked at
the tcc man page. As best I can tell, tcc simply silently
ignores the -fPIC option.
I think that it tries to be a drop-in replacement for gcc, so supports
some of its options, even if they don't do anything. Like -O3.
Position-independent code seems to be a recent thing with gcc tools. My
tools didn't support it either, until a year ago when I found out about
ASLR.
gcc has supported generating position independent code for at
over a quarter of a century.
For most, PIC isn't a necessity.
That's your opinion.
I don't think it matches reality.
And for most of /my/ compiles, the code produced by gcc-O0 is fast
enough. It also about the same speed as code produced by one of my
compilers.
So I tend to use it when I want the extra speed, or other compilers
don't work, or when a particular app only builds with that compiler.
Otherwise the extra overheads are not worth the bother.
For most, PIC isn't a necessity.
On 27/06/2024 20:51, David Brown wrote:
On 27/06/2024 18:28, bart wrote:
On 27/06/2024 13:31, David Brown wrote:
On 27/06/2024 13:16, bart wrote:
No one doubts that gcc is slower than tcc. That is primarily because
it does vastly more, and is a vastly more useful tool. And for most C
compiles, gcc (even gcc -O2) is more than fast enough.
And for most of /my/ compiles, the code produced by gcc-O0 is fast
enough. It also about the same speed as code produced by one of my
compilers.
So I tend to use it when I want the extra speed, or other compilers
don't work, or when a particular app only builds with that compiler.
Otherwise the extra overheads are not worth the bother.
And it is free, and easily available on common systems. Therefore
there is no benefit to using tcc except in very niche cases.
And my argument would be the opposite. The use of gcc would be the
exception. (Long before I used gcc or tcc, I used lccwin32.)
Here's the result of an experiment I did. gcc 14 is about 800MB and over 10,000 files. I wanted to see the minimal set of files that would
compile one of my generated C files.
I can't explain to somebody who doesn't get it why a small, simple tool
is desirable.
On 2024-06-27, bart <bc@freeuk.com> wrote:
For most, PIC isn't a necessity.
Only because they use a virtual memory operating system which allows
every executable to be mapped to the same fixed address in its own
address space.
If you designed your personal OS, which would be the case?
[ ] Programs must be PIC
[ ] Programs needn't be PIC
and Borland, as well as gcc in various packagings. (And embedded
developers use whatever cross-compile tools are appropriate for their
target, regardless of the host - the great majority use gcc now.)
On 27/06/2024 23:47, bart wrote:
On 27/06/2024 20:51, David Brown wrote:
On 27/06/2024 18:28, bart wrote:
On 27/06/2024 13:31, David Brown wrote:
On 27/06/2024 13:16, bart wrote:
No one doubts that gcc is slower than tcc. That is primarily because
it does vastly more, and is a vastly more useful tool. And for most
C compiles, gcc (even gcc -O2) is more than fast enough.
And for most of /my/ compiles, the code produced by gcc-O0 is fast
enough. It also about the same speed as code produced by one of my
compilers.
With most of your compiles, is "gcc -O2" too slow to compile? If not,
then why would you or anyone else actively /choose/ to have a poorer
quality output and poorer quality warnings? I appreciate that fast
enough output is fast enough (just as I say the same for compilation
speed) - but choosing a slower output when a faster one is just as easy
makes little sense. The only reason I can think of why "gcc -O2 -Wall"
is not the starting point for compiler flags is because you write poor C
code and don't want your compiler to tell you so!
So I tend to use it when I want the extra speed, or other compilers
don't work, or when a particular app only builds with that compiler.
Otherwise the extra overheads are not worth the bother.
And it is free, and easily available on common systems. Therefore
there is no benefit to using tcc except in very niche cases.
And my argument would be the opposite. The use of gcc would be the
exception. (Long before I used gcc or tcc, I used lccwin32.)
On Linux, almost everyone uses gcc, except for a proportion who actively choose to use clang or icc. The same applies to other many other *nix systems, though some people will use their system compiler on commercial Unixes. For Macs, it is clang disguised as gcc that dominates. On Windows, few people use C for native code (C++, C# and other languages dominate). I expect the majority use MSVC for C, and there will be
people using a variety of other tools including lcc-win and Borland, as
well as gcc in various packagings. (And embedded developers use
whatever cross-compile tools are appropriate for their target,
regardless of the host - the great majority use gcc now.)
I don't believe that in any graph of compiler usage on any platform, tcc would show up as anything more than a tiny sliver under "others".
Here's the result of an experiment I did. gcc 14 is about 800MB and
over 10,000 files. I wanted to see the minimal set of files that would
compile one of my generated C files.
Why? 800 MB is a few pence worth of disk space. For almost all uses,
it simply doesn't matter.
I can't explain to somebody who doesn't get it why a small, simple
tool is desirable.
If you were trying to say that tcc is simpler to /use/ than gcc, that
would be a different matter entirely. That would be a relevant factor.
The size of the gcc installation, is all hidden behind the scenes. Few people know how big it is on their system, fewer still care.
(And I am not sure I agree with such a claim - certainly you /can/ have
very advanced and complicated use of gcc. But in comparison to learning
C itself, running "gcc -Wall -O2 -o hello hello.c" is hardly rocket science. But I would certainly be much more open to a "simpler to use" argument.)
On 2024-06-27, bart <bc@freeuk.com> wrote:
And for most of /my/ compiles, the code produced by gcc-O0 is fast
enough. It also about the same speed as code produced by one of my
compilers.
So I tend to use it when I want the extra speed, or other compilers
don't work, or when a particular app only builds with that compiler.
Otherwise the extra overheads are not worth the bother.
How good are your diagnostics compared to GCC -O2, plus -Wall and -W?
On 28/06/2024 04:23, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
And for most of /my/ compiles, the code produced by gcc-O0 is fast
enough. It also about the same speed as code produced by one of my
compilers.
So I tend to use it when I want the extra speed, or other compilers
don't work, or when a particular app only builds with that compiler.
Otherwise the extra overheads are not worth the bother.
How good are your diagnostics compared to GCC -O2, plus -Wall and -W?
Using products like tcc doesn't mean never using gcc. (Especially on
Linux where you will have it installed anyway.)
You can use the latter to do extra, periodic checks that the simpler
compiler may have missed, or to produce faster production builds.
But gcc is not needed for routine compilation.
bart <bc@freeuk.com> writes:
On 27/06/2024 21:23, Tim Rentsch wrote:
After taking care of all that the build did manage to produce an
executable, which appears to have run successfully.
After doing a trial run with the produced executable, I looked at
the tcc man page. As best I can tell, tcc simply silently
ignores the -fPIC option.
I think that it tries to be a drop-in replacement for gcc, so supports
some of its options, even if they don't do anything. Like -O3.
Position-independent code seems to be a recent thing with gcc tools. My
tools didn't support it either, until a year ago when I found out about
ASLR.
gcc has supported generating position independent code for at
over a quarter of a century.
For most, PIC isn't a necessity.
That's your opinion. I don't think it matches reality.
For most applications it doesn't matter and PIC code
works just as well as PDC.
On 2024-06-27, bart <bc@freeuk.com> wrote:
For most, PIC isn't a necessity.
Only because they use a virtual memory operating system which allows
every executable to be mapped to the same fixed address in its own
address space.
If you designed your personal OS, which would be the case?
[ ] Programs must be PIC
[ ] Programs needn't be PIC
On 28/06/2024 04:30, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
For most, PIC isn't a necessity.
Only because they use a virtual memory operating system which allows
every executable to be mapped to the same fixed address in its own
address space.
PIC never seemed to be a requirement during the 1980s and half the 90s.
But then OSes only ran one program a time.
And when virtual addressing came along, and multiple programs could
co-exist at the same address, PIC wasn't really needed either.
If you designed your personal OS, which would be the case?
[ ] Programs must be PIC
[ ] Programs needn't be PIC
With or without virtual addressing?
On Fri, 28 Jun 2024 06:56:41 +0200
David Brown <david.brown@hesbynett.no> wrote:
and Borland, as well as gcc in various packagings. (And embedded
developers use whatever cross-compile tools are appropriate for their
target, regardless of the host - the great majority use gcc now.)
I am not sure that it is still true.
Vendors like TI and ST Micro push users of their ARMv7-M development
suits toward clang. I didn't look at NXP lately, but would be surprised
if it's not the same.
On 28/06/2024 00:58, Scott Lurndal wrote:
bart <bc@freeuk.com> writes:
Position-independent code seems to be a recent thing with gcc tools. My
tools didn't support it either, until a year ago when I found out about
ASLR.
gcc has supported generating position independent code for at
over a quarter of a century.
I'm pretty sure that just 4 years ago, I was able to generate non-PIC
object files that could be linked with gcc-ld on Windows.
bart <bc@freeuk.com> writes:
On 28/06/2024 04:30, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
For most, PIC isn't a necessity.
Only because they use a virtual memory operating system which allows
every executable to be mapped to the same fixed address in its own
address space.
PIC never seemed to be a requirement during the 1980s and half the 90s.
But then OSes only ran one program a time.
Interactive operating systems in 1967 (e.g. TSS8) were running
multiple programs at a time.
And when virtual addressing came along, and multiple programs could
co-exist at the same address, PIC wasn't really needed either.
Virtual addressing has been part of computer systems since the 1960s.
PIC is obviously necessary for any kind of shared code (shared object
or DLL) that gets loaded at different base addressses in different
processes.
bart <bc@freeuk.com> writes:
On 28/06/2024 04:30, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
For most, PIC isn't a necessity.
Only because they use a virtual memory operating system which allows
every executable to be mapped to the same fixed address in its own
address space.
PIC never seemed to be a requirement during the 1980s and half the 90s.
But then OSes only ran one program a time.
Interactive operating systems in 1967 (e.g. TSS8) were running
multiple programs at a time.
And when virtual addressing came along, and multiple programs could
co-exist at the same address, PIC wasn't really needed either.
Virtual addressing has been part of computer systems since the 1960s.
On 28/06/2024 14:48, Scott Lurndal wrote:
bart <bc@freeuk.com> writes:
On 28/06/2024 04:30, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
For most, PIC isn't a necessity.
Only because they use a virtual memory operating system which allows
every executable to be mapped to the same fixed address in its own
address space.
PIC never seemed to be a requirement during the 1980s and half the 90s.
But then OSes only ran one program a time.
Interactive operating systems in 1967 (e.g. TSS8) were running
multiple programs at a time.
OK, let's say the many millions of PCs used by home and business in that
era only ran a program at a time.
And when virtual addressing came along, and multiple programs could
co-exist at the same address, PIC wasn't really needed either.
Virtual addressing has been part of computer systems since the 1960s.
OK, so was PIC needed for those or not?
Did all processes share one virtual address space, or did each have its own?
On 28/06/2024 14:48, Scott Lurndal wrote:
bart <bc@freeuk.com> writes:
On 28/06/2024 04:30, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
For most, PIC isn't a necessity.
Only because they use a virtual memory operating system which allows
every executable to be mapped to the same fixed address in its own
address space.
PIC never seemed to be a requirement during the 1980s and half the 90s.
But then OSes only ran one program a time.
Interactive operating systems in 1967 (e.g. TSS8) were running
multiple programs at a time.
And when virtual addressing came along, and multiple programs could
co-exist at the same address, PIC wasn't really needed either.
Virtual addressing has been part of computer systems since the 1960s.
PIC is obviously necessary for any kind of shared code (shared object
or DLL) that gets loaded at different base addressses in different
processes.
I wouldn't call that PIC. On Windows, DLLs need base-relocation tables.
On Mon, 24 Jun 2024 15:00:26 +0100
bart <bc@freeuk.com> wrote:
On 24/06/2024 14:09, Michael S wrote:
On Fri, 21 Jun 2024 22:47:46 +0100
bart <bc@freeuk.com> wrote:
On 21/06/2024 14:34, David Brown wrote:
On 21/06/2024 12:42, bart wrote:
On 21/06/2024 10:46, David Brown wrote:
I understand your viewpoint and motivation. But my own
experience is mostly different.
First, to get it out of the way, there's the speed of
compilation. While heavy optimisation (-O3) can take
noticeably longer, I never see -O0 as being in any noticeable
way faster for compilation than -O1 or even -O2.
Absolute time or relative?
Both.
For me, optimised options with gcc always take longer:
Of course. But I said it was not noticeable - it does not make
enough difference in speed for it to be worth choosing.
C:\c>tm gcc bignum.c -shared -s -obignum.dll # from
cold TM: 3.85
Cold build times are irrelevant to development - when you are
working on a project, all the source files and all your compiler
files are in the PC's cache.
C:\c>tm gcc bignum.c -shared -s -obignum.dll
TM: 0.31
C:\c>tm gcc bignum.c -shared -s -obignum.dll -O2
TM: 0.83
C:\c>tm gcc bignum.c -shared -s -obignum.dll -O3
TM: 0.93
C:\c>dir bignum.dll
21/06/2024 11:14 35,840 bignum.dll
Any build time under a second is as good as instant.
I tested on a real project, not a single file. It has 158 C
files and about 220 header files. And I ran it on my old PC,
without any "tricks" that you dislike so much, doing full clean
re-builds. The files are actually all compiled twice, building
two variants of the binary.
With -O2, it took 34.3 seconds to build. With -O1, it took 33.4
seconds. With -O0, it took 30.8 seconds.
So that is a 15% difference for full builds. In practice, of
course, full rebuilds are rarely needed, and most builds after
changes to the source are within a second or so.
Then there's something very peculiar about your codebase.
To me it looks more likely that your codebase is very unusual
rather than David's
In order to get meaningful measurements I took embedded project
that is significantly bigger than average by my standards. Here
are times of full parallel rebuild (make -j5) on relatively old
computer (4-core Xeon E3-1271 v3).
Option time(s) -g time text size
-O0 13.1 13.3 631648
-Os 13.6 14.1 424016
-O1 13.5 13.7 455728
-O2 14.0 14.1 450056
-O3 14.0 14.6 525380
The difference in time between different -O settings in my
measurements is even smaller than reported by David Brown. That
can be attributed to older compiler (gcc 4.1.2). Another
difference is that this compiler works under cygwin, which is significantly slower both than native Linux and than native
Windows. That causes relatively higher make overhead and longer
link.
I don't know why Cygwin would make much difference; the native code
is still running on the same processor.
I don't know specific reasons. Bird's eye perspective is that cygwin
tries to emulate Posix semantics on platform that is not Posix and
achieves that by using few low-granularity semaphores in user space,
which seriously limits parallelism. Besides, there are problems with emulation of Posix I/O semantics that cause cygwin file I/O to be 2-3
times slower that native Windows I/O. The later applies mostly to
relatively small files, but, then again, software build mostly
accesses small files.
As a matter of fact, a parallel speed up I see on this project on this quad-core machine is barely 2x. I expect 3x or a little more for the
same project with native Windows tools.
"Virtual" by definition means that they have their own address space.
bart <bc@freeuk.com> writes:
On 28/06/2024 14:48, Scott Lurndal wrote:
bart <bc@freeuk.com> writes:
On 28/06/2024 04:30, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
For most, PIC isn't a necessity.
Only because they use a virtual memory operating system which allows >>>>> every executable to be mapped to the same fixed address in its own
address space.
PIC never seemed to be a requirement during the 1980s and half the 90s. >>>> But then OSes only ran one program a time.
Interactive operating systems in 1967 (e.g. TSS8) were running
multiple programs at a time.
And when virtual addressing came along, and multiple programs could
co-exist at the same address, PIC wasn't really needed either.
Virtual addressing has been part of computer systems since the 1960s.
PIC is obviously necessary for any kind of shared code (shared object
or DLL) that gets loaded at different base addressses in different
processes.
I wouldn't call that PIC. On Windows, DLLs need base-relocation tables.
DLL code cannot, for example, use the movabs instruction or any
other instruction that takes absolute addresses;
relocatable code generated needs to be position independent.
Trying to fixup
non-PIC code at load time is fraught and pointless when compilers
have the capability of generating PIC code.
Only external interfaces (function addresses, global variables) should
need relocation tables (GOT and PLT for ELF).
Your experiences seem limited to PC systems.
On Fri, 28 Jun 2024 06:56:41 +0200
David Brown <david.brown@hesbynett.no> wrote:
and Borland, as well as gcc in various packagings. (And embedded
developers use whatever cross-compile tools are appropriate for their
target, regardless of the host - the great majority use gcc now.)
I am not sure that it is still true.
Vendors like TI and ST Micro push users of their ARMv7-M development
suits toward clang. I didn't look at NXP lately, but would be surprised
if it's not the same.
It's not like dev can't chose gcc with this suits,
but it takes effort that majority of embedded code monkeys is
incapable of and majority of minority sees no reason.
gcc toolchains are free, and the standard from manufacturers for a very
long time. The others are very expensive, and it's very questionable if
they actually provide much extra value for most development teams.
(They /do/ provide better tools for some kinds of development.)
Consequently, gcc is overwhelmingly the most popular.
On 28/06/2024 04:23, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
And for most of /my/ compiles, the code produced by gcc-O0 is fast
enough. It also about the same speed as code produced by one of my
compilers.
So I tend to use it when I want the extra speed, or other compilers
don't work, or when a particular app only builds with that compiler.
Otherwise the extra overheads are not worth the bother.
How good are your diagnostics compared to GCC -O2, plus -Wall and -W?
Using products like tcc doesn't mean never using gcc. (Especially on
Linux where you will have it installed anyway.)
You can use the latter to do extra, periodic checks that the simpler
compiler may have missed, or to produce faster production builds.
But gcc is not needed for routine compilation.
On 28/06/2024 12:19, bart wrote:
On 28/06/2024 04:23, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
And for most of /my/ compiles, the code produced by gcc-O0 is fast
enough. It also about the same speed as code produced by one of my
compilers.
So I tend to use it when I want the extra speed, or other compilers
don't work, or when a particular app only builds with that compiler.
Otherwise the extra overheads are not worth the bother.
How good are your diagnostics compared to GCC -O2, plus -Wall and -W?
Using products like tcc doesn't mean never using gcc. (Especially on
Linux where you will have it installed anyway.)
You can use the latter to do extra, periodic checks that the simpler
compiler may have missed, or to produce faster production builds.
But gcc is not needed for routine compilation.
It is certainly a reasonable idea to use gcc as a linter if your normal compile is poor at static checking. I've done that myself in the past -
in embedded development, you don't always get to choose a good compiler.
 These days I'd be more likely to go for clang-tidy as a linter, and there's other more advanced tools available (especially if you have the money).
However, I don't see the point in doing any kind of compilation at all,
until you have at least basic linting and static error checking in
place. If I've used the value of a variable without initialising it, I
have no interest in running the program until that is fixed.
 And if I
don't want to run the program, I've no interest in compiling it.
So I simply can't comprehend why you'd want fast but pointless compiles regularly, then only occasionally check to see if the code is actually correct - or at least, does not contain detectable errors
Now, if you were using one of these "big" linters that does simulations
of your code and takes hours to run on a server machine before posting
back a report, that's a different matter. Tools like that run overnight
or in batches, integrating with version control systems, automatic test setups, and so on. But that's not what we are talking about.
Say tcc takes 0.2 seconds to compile your code, and "gcc -O2 -Wall"
takes 3 seconds. If gcc catches an error that you missed, that's
probably going to save you between half and hour and several days
finding the problem by trial-and-error debugging.
On 2024-06-28, bart <bc@freeuk.com> wrote:
On 28/06/2024 04:23, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
And for most of /my/ compiles, the code produced by gcc-O0 is fast
enough. It also about the same speed as code produced by one of my
compilers.
So I tend to use it when I want the extra speed, or other compilers
don't work, or when a particular app only builds with that compiler.
Otherwise the extra overheads are not worth the bother.
How good are your diagnostics compared to GCC -O2, plus -Wall and -W?
Using products like tcc doesn't mean never using gcc. (Especially on
Linux where you will have it installed anyway.)
You can use the latter to do extra, periodic checks that the simpler
compiler may have missed, or to produce faster production builds.
But gcc is not needed for routine compilation.
Catching common bugs in routine compilation is better than once
a month.
You could be wasting time debugging something where GCC would have told
you right away you have something uninitialized or whatever.
On 28/06/2024 11:26, Kaz Kylheku wrote:
On 2024-06-28, bart <bc@freeuk.com> wrote:
On 28/06/2024 04:23, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
And for most of /my/ compiles, the code produced by gcc-O0 is
fast enough. It also about the same speed as code produced by
one of my compilers.
So I tend to use it when I want the extra speed, or other
compilers don't work, or when a particular app only builds
with that compiler.
Otherwise the extra overheads are not worth the bother.
How good are your diagnostics compared to GCC -O2, plus -Wall
and -W?
Using products like tcc doesn't mean never using gcc.
(Especially on Linux where you will have it installed anyway.)
You can use the latter to do extra, periodic checks that the
simpler compiler may have missed, or to produce faster production
builds.
But gcc is not needed for routine compilation.
Catching common bugs in routine compilation is better than once
a month.
You could be wasting time debugging something where GCC would have
told you right away you have something uninitialized or whatever.
Let's take the C program below. It has 4 things wrong with it,
marked with comments.
[...]
bart <bc@freeuk.com> writes:
On 28/06/2024 11:26, Kaz Kylheku wrote:
On 2024-06-28, bart <bc@freeuk.com> wrote:
On 28/06/2024 04:23, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
And for most of /my/ compiles, the code produced by gcc-O0 is
fast enough. It also about the same speed as code produced by
one of my compilers.
So I tend to use it when I want the extra speed, or other
compilers don't work, or when a particular app only builds
with that compiler.
Otherwise the extra overheads are not worth the bother.
How good are your diagnostics compared to GCC -O2, plus -Wall
and -W?
Using products like tcc doesn't mean never using gcc.
(Especially on Linux where you will have it installed anyway.)
You can use the latter to do extra, periodic checks that the
simpler compiler may have missed, or to produce faster production
builds.
But gcc is not needed for routine compilation.
Catching common bugs in routine compilation is better than once
a month.
You could be wasting time debugging something where GCC would have
told you right away you have something uninitialized or whatever.
Let's take the C program below. It has 4 things wrong with it,
marked with comments.
[...]
People are never going to take you seriously as long as
you keep offering what are obviously strawman arguments,
and especially ones where you know better but pretend
that you don't.
On 2024-06-29, David Brown <david.brown@hesbynett.no> wrote:
gcc toolchains are free, and the standard from manufacturers for a very
long time. The others are very expensive, and it's very questionable if
they actually provide much extra value for most development teams.
(They /do/ provide better tools for some kinds of development.)
Consequently, gcc is overwhelmingly the most popular.
One thing: builds having to talk to some god forsaken licensing server
to get permission to compile is beyond ridiculous.
My older bcc compiler reported 4 as a hard error unless an override was
used.
-------------------------
#include <stdio.h>
#include <stdlib.h>
int F(void) {
   return;            // 1 No value
}
int G(void) {
   if (rand())
       return 0;
}Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â // 2 Possibly running into end
int main() {
   char s[10];
   char *p = &s;      // 3 Wrong types
   main(123);         // 4 Unchecked arg types
}
-------------------------
On 29/06/2024 16:38, Tim Rentsch wrote:
bart <bc@freeuk.com> writes:
On 28/06/2024 11:26, Kaz Kylheku wrote:
On 2024-06-28, bart <bc@freeuk.com> wrote:
On 28/06/2024 04:23, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
And for most of /my/ compiles, the code produced by gcc-O0 is
fast enough. It also about the same speed as code produced by
one of my compilers.
So I tend to use it when I want the extra speed, or other
compilers don't work, or when a particular app only builds
with that compiler.
Otherwise the extra overheads are not worth the bother.
How good are your diagnostics compared to GCC -O2, plus -Wall
and -W?
Using products like tcc doesn't mean never using gcc.
(Especially on Linux where you will have it installed anyway.)
You can use the latter to do extra, periodic checks that the
simpler compiler may have missed, or to produce faster production
builds.
But gcc is not needed for routine compilation.
Catching common bugs in routine compilation is better than once
a month.
You could be wasting time debugging something where GCC would have
told you right away you have something uninitialized or whatever.
Let's take the C program below. It has 4 things wrong with it,
marked with comments.
[...]
People are never going to take you seriously as long as
you keep offering what are obviously strawman arguments,
and especially ones where you know better but pretend
that you don't.
You've perhaps missed my main point, which was that gcc 14 now reports
hard errors BY DEFAULT for things which I have argued in the past should
be hard errors by default.
You've probably also missed my secondary point, which was asking WHY
that change was made, since all that people had to do to get that
behaviour was to jump through a number of hoops as I've always been told
to do. Apparently that was not good enough!
I've also learnt something interesting. Which is that whatever the
current version of gcc does is always right, and I'm always wrong if I suggest it should be any different.
But if gcc suddenly starts doing what I'd advocated, then according to
you I'm still wrong! So I can never win.
On 2024-06-29, David Brown <david.brown@hesbynett.no> wrote:
gcc toolchains are free, and the standard from manufacturers for a very
long time. The others are very expensive, and it's very questionable if
they actually provide much extra value for most development teams.
(They /do/ provide better tools for some kinds of development.)
Consequently, gcc is overwhelmingly the most popular.
One thing: builds having to talk to some god forsaken licensing server
to get permission to compile is beyond ridiculous.
gcc, however, is restricted and limited by its past - the developers
do not lightly make changes that will result in compilation failures
of code that previously compiled fine and had been tested to run
correctly. Such changes - as made for gcc 14 - are only done after
long discussion and long testing with existing code bases.
On 29/06/2024 15:14, bart wrote:
[...]
My older bcc compiler reported 4 as a hard error unless an override
was used.
But you didn't say anything about main's args.
You've perhaps missed my main point, which was that gcc 14 now reports
hard errors BY DEFAULT for things which I have argued in the past should
be hard errors by default.
You've probably also missed my secondary point, which was asking WHY
that change was made, since all that people had to do to get that
behaviour was to jump through a number of hoops as I've always been told
to do. Apparently that was not good enough!
I've also learnt something interesting. Which is that whatever the
current version of gcc does is always right, and I'm always wrong if I suggest it should be any different.
On Sat, 29 Jun 2024 19:42:01 +0200
David Brown <david.brown@hesbynett.no> wrote:
gcc, however, is restricted and limited by its past - the developers
do not lightly make changes that will result in compilation failures
of code that previously compiled fine and had been tested to run
correctly. Such changes - as made for gcc 14 - are only done after
long discussion and long testing with existing code bases.
Default input dialect of C language was changed (it seems, to gnu17)
before gcc14. May be, in gcc12.
BTW, finding out what dialect is a defaul is less than trivial.
On 29/06/2024 16:38, Tim Rentsch wrote:
bart <bc@freeuk.com> writes:
On 28/06/2024 11:26, Kaz Kylheku wrote:
On 2024-06-28, bart <bc@freeuk.com> wrote:
On 28/06/2024 04:23, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
And for most of /my/ compiles, the code produced by gcc-O0 is
fast enough. It also about the same speed as code produced by
one of my compilers.
So I tend to use it when I want the extra speed, or other
compilers don't work, or when a particular app only builds
with that compiler.
Otherwise the extra overheads are not worth the bother.
How good are your diagnostics compared to GCC -O2, plus -Wall
and -W?
Using products like tcc doesn't mean never using gcc.
(Especially on Linux where you will have it installed anyway.)
You can use the latter to do extra, periodic checks that the
simpler compiler may have missed, or to produce faster production
builds.
But gcc is not needed for routine compilation.
Catching common bugs in routine compilation is better than once
a month.
You could be wasting time debugging something where GCC would have
told you right away you have something uninitialized or whatever.
Let's take the C program below. It has 4 things wrong with it,
marked with comments.
[...]
People are never going to take you seriously as long as
you keep offering what are obviously strawman arguments,
and especially ones where you know better but pretend
that you don't.
You've perhaps missed my main point,
You've probably also missed my secondary point,
I've also learnt something interesting. Which is that whatever the
current version of gcc does is always right, and I'm always wrong if I suggest it should be any different.
On 29/06/2024 09:47, David Brown wrote:
On 28/06/2024 12:19, bart wrote:
On 28/06/2024 04:23, Kaz Kylheku wrote:
On 2024-06-27, bart <bc@freeuk.com> wrote:
And for most of /my/ compiles, the code produced by gcc-O0 is fast
enough. It also about the same speed as code produced by one of my
compilers.
So I tend to use it when I want the extra speed, or other compilers
don't work, or when a particular app only builds with that compiler. >>>>>
Otherwise the extra overheads are not worth the bother.
How good are your diagnostics compared to GCC -O2, plus -Wall and -W?
Using products like tcc doesn't mean never using gcc. (Especially on
Linux where you will have it installed anyway.)
;
You can use the latter to do extra, periodic checks that the simpler
compiler may have missed, or to produce faster production builds.
But gcc is not needed for routine compilation.
It is certainly a reasonable idea to use gcc as a linter if your
normal compile is poor at static checking. I've done that myself in
the past - in embedded development, you don't always get to choose a
good compiler. Â Â These days I'd be more likely to go for clang-tidy as
a linter, and there's other more advanced tools available (especially
if you have the money).
However, I don't see the point in doing any kind of compilation at
all, until you have at least basic linting and static error checking
in place. If I've used the value of a variable without initialising
it, I have no interest in running the program until that is fixed.
You run the program, and if it doesn't work or has some bug that you
can't figure out, then you can pass it through a bigger compiler to get
its opinion.
If the program works, then you can still do that to pick up things
you've missed, in case the program worked by luck. But this doesn't need
to be done every time.
I wonder, how do you work with Python. Presumably there you're used to
making frequent small tweaks (maybe lining up some output) and running
it immediately to check it's OK.
If there was some elaborate checker for Python code, or you had an
extensive test suite that executed all lines of the program to check you hadn't mispelled anything, I expect you wouldn't to run those after
every minor edit.
You use Python /because/ it's quick and informal.
 And if I don't want to run the program, I've no interest in
compiling it.
So I simply can't comprehend why you'd want fast but pointless
compiles regularly, then only occasionally check to see if the code is
actually correct - or at least, does not contain detectable errors
For similar reasons that drivers don't stop to check their tyre
pressures every mile. Or why MOTs (inspections) are only mandated once a year.
Now, if you were using one of these "big" linters that does
simulations of your code and takes hours to run on a server machine
before posting back a report, that's a different matter. Tools like
that run overnight or in batches, integrating with version control
systems, automatic test setups, and so on. But that's not what we are
talking about.
Say tcc takes 0.2 seconds to compile your code, and "gcc -O2 -Wall"
takes 3 seconds. If gcc catches an error that you missed, that's
probably going to save you between half and hour and several days
finding the problem by trial-and-error debugging.
Take any kind of interactive work done on a computer - editing a source
file, doing creative writing, writing a reply on a forum, all sorts of
stuff you expect to work smoothly.
Now imagine that every so often it freezes for several seconds. (This is exactly what used to happen on Thunderbird last year. It's what happens
now on one of my smart TV apps, there can be several seconds latency
after pressing a button on the remote.)
It would be incredibly annoying. It would break your concentration. It
would make some things impractical (I don't use the smart TV app; I
browse on my PC instead.)
That is what gcc is like to me. There is no fluency. YMMV.
On Sat, 29 Jun 2024 11:05:41 +0200
David Brown <david.brown@hesbynett.no> wrote:
It does not sound like you know what you are talking about.
Just download latest Arm MCU variant of TI CCS or of STM32 Cube and see.
They are free (like beer) and they are based on clang.
On 29/06/2024 18:46, Richard Harnden wrote:
On 29/06/2024 15:14, bart wrote:
[...]
My older bcc compiler reported 4 as a hard error unless an
override was used.
But you didn't say anything about main's args.
I did, indirectly. The actual error was the use of "()" as an empty
parameter list (for any function, not just main, but my example could
also have been 'void H(){H(123);}'). If you tried to compile:
int main() {
main(123);
}
then it wouldn't get past the () to the call.
Eventually I dropped that restriction, and the reason was that so
much code used such parameter lists, for any function.
Not because they wanted unchecked args (there are some legitimate
use-cases within function pointer types), but because so many people
assumed () meant zero parameters like (void).
Why was such code so common? Presumably because compilers said
nothing; and they couldn't because the language allowed it. If they
had required an override like mine did, more would have got the
message.
Now it's too late because apparently the meaning of () is changing to
mean (void). All those people who got it wrong (and introduced a
dangerous bug) have won!
On Sat, 29 Jun 2024 19:42:01 +0200
David Brown <david.brown@hesbynett.no> wrote:
gcc, however, is restricted and limited by its past - the developers
do not lightly make changes that will result in compilation failures
of code that previously compiled fine and had been tested to run
correctly. Such changes - as made for gcc 14 - are only done after
long discussion and long testing with existing code bases.
Default input dialect of C language was changed (it seems, to gnu17)
before gcc14. May be, in gcc12.
BTW, finding out what dialect is a defaul is less than trivial. If Bart
calls it "jump through a number of hoops" he would at least correct,
but more like understating his case.
On 29/06/2024 13:11, bart wrote:
If there was some elaborate checker for Python code, or you had an
extensive test suite that executed all lines of the program to check
you hadn't mispelled anything, I expect you wouldn't to run those
after every minor edit.
No, not after every edit. But then, I don't compile my C code after
every edit. It depends on the size and type of the edit. Some checks - such as for misspelling - /are/ done continuously during editing, at
least to some extent. A decent IDE or editor will help there.
That is what gcc is like to me. There is no fluency. YMMV.
It is possible to have your cake and eat it. You think this is all a
binary choice - it is not. You can have smooth and fluent development
/and/ powerful checking /and/ efficient generated code /and/
full-featured tools.
On Sat, 29 Jun 2024 20:55:54 +0100
bart <bc@freeuk.com> wrote:
On 29/06/2024 18:46, Richard Harnden wrote:
On 29/06/2024 15:14, bart wrote:
[...]
My older bcc compiler reported 4 as a hard error unless an
override was used.
But you didn't say anything about main's args.
I did, indirectly. The actual error was the use of "()" as an empty
parameter list (for any function, not just main, but my example could
also have been 'void H(){H(123);}'). If you tried to compile:
int main() {
main(123);
}
then it wouldn't get past the () to the call.
Eventually I dropped that restriction, and the reason was that so
much code used such parameter lists, for any function.
Not because they wanted unchecked args (there are some legitimate
use-cases within function pointer types), but because so many people
assumed () meant zero parameters like (void).
Why was such code so common? Presumably because compilers said
nothing; and they couldn't because the language allowed it. If they
had required an override like mine did, more would have got the
message.
I tried following code:
int foo() { return 1; }
Both MSVC and clang warn about it at high warnings level (-Wall for
MSVC, -Wpedantic for clang). But they dont warn at levels that most
people use in practice (-W3 or -W4 for MSVC, -Wall for clang).
gcc13 produces no warning even at -Wpedantic. It does produce warning
with '-Wpedantic -std=xxx' for all values of xxx except c23 and gnu23.
The absence of warning for c23/gnu23 makes sense, the rest of gcc
behavior - less so.
On 30/06/2024 10:05, David Brown wrote:
On 29/06/2024 13:11, bart wrote:
If there was some elaborate checker for Python code, or you had an
extensive test suite that executed all lines of the program to check
you hadn't mispelled anything, I expect you wouldn't to run those
after every minor edit.
No, not after every edit. But then, I don't compile my C code after
every edit. It depends on the size and type of the edit. Some checks
- such as for misspelling - /are/ done continuously during editing, at
least to some extent. A decent IDE or editor will help there.
An IDE or editor which presumably uses some fast aspects of fast
compilation to give you real-time feedback.
I don't use such smart tools and so rely on such feedback from the
compiler.
Many edits to my source code (I realised this last night) consist of commenting or uncommenting one line of code, eg. that may call or not
call some routine, or changing some internal flag to enable something or other, eg. to show extra diagnostics. Or inserting or removing an early return. Or adding or removing or commenting out some diagnostic print statements.
This is not working on the logic of some complex algorithm. It's
changing something on a whim (maybe calling that fixup routine or not)
and needing instant feedback. Here I don't need any deep analysis!
If compilation took a minute, then I might have to use command-line
options instead of editing an internal flag or using commenting. I might
need to use (or develop) a debugger to avoid recompiling. I'd have to
revert (in my language) to independent compilation so I'd only need to compile a small part after any change.
I'd have to use some smart editor to tell me things quicker than a
compiler would (if such an editor understood my language).
This does not sound appealing. More like going back decades.
Perhaps you can understand better why more-or-less instant compilation
can be a useful thing, it eliminates the need for those cumbersome
external solutions, and it keeps my own tools simple.
It opens up possibilities.
That is what gcc is like to me. There is no fluency. YMMV.
It is possible to have your cake and eat it. You think this is all a
binary choice - it is not. You can have smooth and fluent development
/and/ powerful checking /and/ efficient generated code /and/
full-featured tools.
And you could have C development that works just like Python (well,
minus its bundled libraries).
On 30/06/2024 11:18, Michael S wrote:
On Sat, 29 Jun 2024 20:55:54 +0100
bart <bc@freeuk.com> wrote:
On 29/06/2024 18:46, Richard Harnden wrote:
On 29/06/2024 15:14, bart wrote:
[...]
My older bcc compiler reported 4 as a hard error unless an
override was used.
But you didn't say anything about main's args.
I did, indirectly. The actual error was the use of "()" as an empty
parameter list (for any function, not just main, but my example
could also have been 'void H(){H(123);}'). If you tried to compile:
int main() {
main(123);
}
then it wouldn't get past the () to the call.
Eventually I dropped that restriction, and the reason was that so
much code used such parameter lists, for any function.
Not because they wanted unchecked args (there are some legitimate
use-cases within function pointer types), but because so many
people assumed () meant zero parameters like (void).
Why was such code so common? Presumably because compilers said
nothing; and they couldn't because the language allowed it. If they
had required an override like mine did, more would have got the
message.
I tried following code:
int foo() { return 1; }
Both MSVC and clang warn about it at high warnings level (-Wall for
MSVC, -Wpedantic for clang). But they dont warn at levels that most
people use in practice (-W3 or -W4 for MSVC, -Wall for clang).
gcc13 produces no warning even at -Wpedantic. It does produce
warning with '-Wpedantic -std=xxx' for all values of xxx except c23
and gnu23. The absence of warning for c23/gnu23 makes sense, the
rest of gcc behavior - less so.
gcc -Wpedantic makes very little sense without specifying a C
standard (rather than a gnu C standard).
But why would you expect a warning from code that is perfectly legal
and well-defined C code, without explicitly enabling warnings that
check for particular style issues? Non-prototype function
declarations are deprecated (since C99), but not removed from the
language until C23 (where that declaration is now a function
prototype).
On Sun, 30 Jun 2024 17:54:14 +0200
David Brown <david.brown@hesbynett.no> wrote:
But why would you expect a warning from code that is perfectly legal
and well-defined C code, without explicitly enabling warnings that
check for particular style issues? Non-prototype function
declarations are deprecated (since C99), but not removed from the
language until C23 (where that declaration is now a function
prototype).
I expect warning at -Wall, because it is deprecated. Those who do
not want warning can turn it off explicitly with -Wno-strict-prototypes
or whatever the name of the switch.
Using products like tcc doesn't mean never using gcc. (Especially on Linux where you will have it installed anyway.)
On 30/06/2024 12:48, bart wrote:
It opens up possibilities.
It opens possibilities for doing lots more manual work, making more
mistakes, finding those mistakes later, and generally working in a way
most people were glad to move away from a generation ago.
Fast compilation is fine and good in itself. And I can understand
feeling that giant IDE's like Eclipse or MS Code are bigger than you
want, and take time to learn. But it is incomprehensible to me that
you'd /want/ to use such limited tools as you do.
bart <bc@freeuk.com> writes:
Using products like tcc doesn't mean never using gcc. (Especially on Linux >> where you will have it installed anyway.)
The parenthetical remark is wrong.
On 01/07/2024 13:09, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
Using products like tcc doesn't mean never using gcc. (Especially on Linux >>> where you will have it installed anyway.)The parenthetical remark is wrong.
You mean it is possible for a Linux installation to not have gcc preinstalled?
Sure, although in the dozen or two versions I've come across, it
always has been.
bart <bc@freeuk.com> writes:
On 01/07/2024 13:09, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
Using products like tcc doesn't mean never using gcc. (Especially on Linux >>>> where you will have it installed anyway.)The parenthetical remark is wrong.
You mean it is possible for a Linux installation to not have gcc
preinstalled?
I mean that saying "on Linux ... you will have it installed anyway" is
wrong.
Sure, although in the dozen or two versions I've come across, it
always has been.
I'm not sure what you mean by a "version". Every version (in the sense
of release number) of a source-only Linux distribution will have gcc installed, but is that all you mean? Source-only distributions are rare
and not widely used.
On 02/07/2024 16:00, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 01/07/2024 13:09, Ben Bacarisse wrote:I mean that saying "on Linux ... you will have it installed anyway" is
bart <bc@freeuk.com> writes:
Using products like tcc doesn't mean never using gcc. (Especially on LinuxThe parenthetical remark is wrong.
where you will have it installed anyway.)
You mean it is possible for a Linux installation to not have gcc
preinstalled?
wrong.
Sure, although in the dozen or two versions I've come across, itI'm not sure what you mean by a "version". Every version (in the sense
always has been.
of release number) of a source-only Linux distribution will have gcc
installed, but is that all you mean? Source-only distributions are rare
and not widely used.
No I mean binary distributions (unless the install process silently
compiled from source; I've no idea).
bart <bc@freeuk.com> writes:
On 02/07/2024 16:00, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 01/07/2024 13:09, Ben Bacarisse wrote:I mean that saying "on Linux ... you will have it installed anyway" is
bart <bc@freeuk.com> writes:
Using products like tcc doesn't mean never using gcc. (Especially on LinuxThe parenthetical remark is wrong.
where you will have it installed anyway.)
You mean it is possible for a Linux installation to not have gcc
preinstalled?
wrong.
Sure, although in the dozen or two versions I've come across, itI'm not sure what you mean by a "version". Every version (in the sense
always has been.
of release number) of a source-only Linux distribution will have gcc
installed, but is that all you mean? Source-only distributions are rare >>> and not widely used.
No I mean binary distributions (unless the install process silently
compiled from source; I've no idea).
Which ones?
On 03/07/2024 00:58, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 02/07/2024 16:00, Ben Bacarisse wrote:Which ones?
bart <bc@freeuk.com> writes:
On 01/07/2024 13:09, Ben Bacarisse wrote:I mean that saying "on Linux ... you will have it installed anyway" is >>>> wrong.
bart <bc@freeuk.com> writes:
Using products like tcc doesn't mean never usingThe parenthetical remark is wrong.
gcc. (Especially on Linux
where you will have it installed anyway.)
You mean it is possible for a Linux installation to not have gcc
preinstalled?
Sure, although in the dozen or two versions I've come across, itI'm not sure what you mean by a "version". Every version (in the sense >>>> of release number) of a source-only Linux distribution will have gcc
always has been.
installed, but is that all you mean? Source-only distributions are rare >>>> and not widely used.
No I mean binary distributions (unless the install process silently
compiled from source; I've no idea).
I really, really don't remember.
I really, really don't remember. I've tinkered with Linux every so often
for 20, maybe 25 years. You used to be able to order a job-lot of CDs
with different versions. Few did much.
Then there were various ones I tried under Virtual Box. All had gcc.
On 2024-07-03, bart <bc@freeuk.com> wrote:
I really, really don't remember. I've tinkered with Linux every so often
for 20, maybe 25 years. You used to be able to order a job-lot of CDs
with different versions. Few did much.
Every major distro I've ever used going back ti 1995 made it optional
to install just about everything, including the compiler suite.
A very popular desktop distro is Ubuntu. GCC is not a base package in
Ubuntu.
On 03/07/2024 00:58, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 02/07/2024 16:00, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 01/07/2024 13:09, Ben Bacarisse wrote:I mean that saying "on Linux ... you will have it installed anyway" is >>>> wrong.
bart <bc@freeuk.com> writes:
Using products like tcc doesn't mean never using gcc. (Especially >>>>>>> on LinuxThe parenthetical remark is wrong.
where you will have it installed anyway.)
You mean it is possible for a Linux installation to not have gcc
preinstalled?
Sure, although in the dozen or two versions I've come across, itI'm not sure what you mean by a "version". Every version (in the sense >>>> of release number) of a source-only Linux distribution will have gcc
always has been.
installed, but is that all you mean? Source-only distributions are
rare
and not widely used.
No I mean binary distributions (unless the install process silently
compiled from source; I've no idea).
Which ones?
I really, really don't remember. I've tinkered with Linux every so often
for 20, maybe 25 years. You used to be able to order a job-lot of CDs
with different versions. Few did much.
Then there were various ones I tried under Virtual Box. All had gcc.
I must have tried half a dozen, maybe more, on RPis. Those I know all
had gcc too. So did a laptop or two with Linux. As does WSL now.
I'm not sure what you're trying to do here.
I will admit that it might not be 100% certain that a Linux OS on a
system on which someone is planning to run a C compiler will have gcc installed, although that is not my experience.
Will that do?
On 03/07/2024 02:23, bart wrote:
On 03/07/2024 00:58, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 02/07/2024 16:00, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 01/07/2024 13:09, Ben Bacarisse wrote:I mean that saying "on Linux ... you will have it installed anyway" is >>>>> wrong.
bart <bc@freeuk.com> writes:
Using products like tcc doesn't mean never using gcc.The parenthetical remark is wrong.
(Especially on Linux
where you will have it installed anyway.)
You mean it is possible for a Linux installation to not have gcc
preinstalled?
Sure, although in the dozen or two versions I've come across, itI'm not sure what you mean by a "version". Every version (in the
always has been.
sense
of release number) of a source-only Linux distribution will have gcc >>>>> installed, but is that all you mean? Source-only distributions are >>>>> rare
and not widely used.
No I mean binary distributions (unless the install process silently
compiled from source; I've no idea).
Which ones?
I really, really don't remember. I've tinkered with Linux every so
often for 20, maybe 25 years. You used to be able to order a job-lot
of CDs with different versions. Few did much.
Then there were various ones I tried under Virtual Box. All had gcc.
I must have tried half a dozen, maybe more, on RPis. Those I know all
had gcc too. So did a laptop or two with Linux. As does WSL now.
I'm not sure what you're trying to do here.
I will admit that it might not be 100% certain that a Linux OS on a
system on which someone is planning to run a C compiler will have gcc
installed, although that is not my experience.
Will that do?
In my experience, Linux distributions (which is a much more correct term
than your "versions") rarely install gcc by default, unless they are source-based distributions. But virtually all will have gcc available
for easy installation from their repositories. And they will pull it in automatically if the user installs something that requires it to run, or
to install (such as some kinds of drivers that need to be matched to the kernel being used).
So perhaps instead of insisting, incorrectly, that gcc is almost always installed on Linux, you could just say that gcc is almost always easily available, and move on. (And perhaps it is so easily installed that you
did so without noticing it on your systems.)
On 03/07/2024 08:08, David Brown wrote:
On 03/07/2024 02:23, bart wrote:
On 03/07/2024 00:58, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 02/07/2024 16:00, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 01/07/2024 13:09, Ben Bacarisse wrote:I mean that saying "on Linux ... you will have it installed
bart <bc@freeuk.com> writes:
Using products like tcc doesn't mean never using gcc.The parenthetical remark is wrong.
(Especially on Linux
where you will have it installed anyway.)
You mean it is possible for a Linux installation to not have gcc >>>>>>> preinstalled?
anyway" is
wrong.
Sure, although in the dozen or two versions I've come across, it >>>>>>> always has been.I'm not sure what you mean by a "version". Every version (in the >>>>>> sense
of release number) of a source-only Linux distribution will have gcc >>>>>> installed, but is that all you mean? Source-only distributions
are rare
and not widely used.
No I mean binary distributions (unless the install process silently
compiled from source; I've no idea).
Which ones?
I really, really don't remember. I've tinkered with Linux every so
often for 20, maybe 25 years. You used to be able to order a job-lot
of CDs with different versions. Few did much.
Then there were various ones I tried under Virtual Box. All had gcc.
I must have tried half a dozen, maybe more, on RPis. Those I know all
had gcc too. So did a laptop or two with Linux. As does WSL now.
I'm not sure what you're trying to do here.
I will admit that it might not be 100% certain that a Linux OS on a
system on which someone is planning to run a C compiler will have gcc
installed, although that is not my experience.
Will that do?
In my experience, Linux distributions (which is a much more correct
term than your "versions") rarely install gcc by default, unless they
are source-based distributions. But virtually all will have gcc
available for easy installation from their repositories. And they
will pull it in automatically if the user installs something that
requires it to run, or to install (such as some kinds of drivers that
need to be matched to the kernel being used).
So perhaps instead of insisting, incorrectly, that gcc is almost
always installed on Linux, you could just say that gcc is almost
always easily available, and move on. (And perhaps it is so easily
installed that you did so without noticing it on your systems.)
I've never had to install gcc on any distribution of Linux. That's not
to say it was already installed, but if I ever had to use it, it was there.
Maybe on very early versions, where I struggled to get it to do anything
at all (like support a display) I didn't get around to using a C compiler.
But I did exactly that on all Linuxes installed on Virtual Box, or that
was on that notebook I had, or all the ones I tried across my two RPis,
plus the WSLs I've used.
That's enough of a track record for even one person that one can say,
Linux pretty much always comes with gcc. And if it doesn't, it's easy to install as you say.
On 7/3/2024 5:36 AM, bart wrote:
On 03/07/2024 08:08, David Brown wrote:
On 03/07/2024 02:23, bart wrote:
On 03/07/2024 00:58, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 02/07/2024 16:00, Ben Bacarisse wrote:
bart <bc@freeuk.com> writes:
On 01/07/2024 13:09, Ben Bacarisse wrote:I mean that saying "on Linux ... you will have it installed
bart <bc@freeuk.com> writes:
Using products like tcc doesn't mean never using gcc.The parenthetical remark is wrong.
(Especially on Linux
where you will have it installed anyway.)
You mean it is possible for a Linux installation to not have gcc >>>>>>>> preinstalled?
anyway" is
wrong.
Sure, although in the dozen or two versions I've come across, it >>>>>>>> always has been.I'm not sure what you mean by a "version". Every version (in the >>>>>>> sense
of release number) of a source-only Linux distribution will have gcc >>>>>>> installed, but is that all you mean? Source-only distributions >>>>>>> are rare
and not widely used.
No I mean binary distributions (unless the install process silently >>>>>> compiled from source; I've no idea).
Which ones?
I really, really don't remember. I've tinkered with Linux every so
often for 20, maybe 25 years. You used to be able to order a job-lot
of CDs with different versions. Few did much.
Then there were various ones I tried under Virtual Box. All had gcc.
I must have tried half a dozen, maybe more, on RPis. Those I know
all had gcc too. So did a laptop or two with Linux. As does WSL now. >>>>
I'm not sure what you're trying to do here.
I will admit that it might not be 100% certain that a Linux OS on a
system on which someone is planning to run a C compiler will have
gcc installed, although that is not my experience.
Will that do?
In my experience, Linux distributions (which is a much more correct
term than your "versions") rarely install gcc by default, unless they
are source-based distributions. But virtually all will have gcc
available for easy installation from their repositories. And they
will pull it in automatically if the user installs something that
requires it to run, or to install (such as some kinds of drivers that
need to be matched to the kernel being used).
So perhaps instead of insisting, incorrectly, that gcc is almost
always installed on Linux, you could just say that gcc is almost
always easily available, and move on. (And perhaps it is so easily
installed that you did so without noticing it on your systems.)
I've never had to install gcc on any distribution of Linux. That's not
to say it was already installed, but if I ever had to use it, it was
there.
Maybe on very early versions, where I struggled to get it to do
anything at all (like support a display) I didn't get around to using
a C compiler.
But I did exactly that on all Linuxes installed on Virtual Box, or
that was on that notebook I had, or all the ones I tried across my two
RPis, plus the WSLs I've used.
That's enough of a track record for even one person that one can say,
Linux pretty much always comes with gcc. And if it doesn't, it's easy
to install as you say.
distrowatch.com shows most distros come with gcc preinstalled.
I think Windows should come with various development tools and programs preinstalled and ready to go: tcc, python, VS Code, SQLite.
Windows itself is primarily a consumer product not a DIY OS as Linux
comes across.
Although I wouldn't mind if some of those were available; they would
take up an insignificant amount of space compared to the rest of
Windows. And would open interesting possibilities, such as supplying
some programs as source code.
It also needs a better built-in scripting language than 'BAT' scripts.
Situations which are constraint or syntax violations in ISO C, where the compiler is not providing a useful extensions, should be diagnosed in
such a way that translation does not succeed.
ISO C doesn't require that, possibly because it would forbid extensions. (Extensions that are non-conforming, but only in the regard that
translation doesn't fail.)
distrowatch.com shows most distros come with gcc preinstalled.
That's enough of a track record for even one person that one can say,
Linux pretty much always comes with gcc.
And if it doesn't, it's easy to
install as you say.
On 7/3/2024 5:36 AM, bart wrote:
That's enough of a track record for even one person that one can say,
Linux pretty much always comes with gcc. And if it doesn't, it's easy
to install as you say.
distrowatch.com shows most distros come with gcc preinstalled.
I think Windows should come with various development tools and programs preinstalled and ready to go: tcc, python, VS Code, SQLite.
On Sun, 30 Jun 2024 17:54:14 +0200
David Brown <david.brown@hesbynett.no> wrote:
On 30/06/2024 11:18, Michael S wrote:
On Sat, 29 Jun 2024 20:55:54 +0100
bart <bc@freeuk.com> wrote:
On 29/06/2024 18:46, Richard Harnden wrote:
On 29/06/2024 15:14, bart wrote:
[...]
My older bcc compiler reported 4 as a hard error unless an
override was used.
But you didn't say anything about main's args.
I did, indirectly. The actual error was the use of "()" as an empty
parameter list (for any function, not just main, but my example
could also have been 'void H(){H(123);}'). If you tried to compile:
int main() {
main(123);
}
then it wouldn't get past the () to the call.
Eventually I dropped that restriction, and the reason was that so
much code used such parameter lists, for any function.
Not because they wanted unchecked args (there are some legitimate
use-cases within function pointer types), but because so many
people assumed () meant zero parameters like (void).
Why was such code so common? Presumably because compilers said
nothing; and they couldn't because the language allowed it. If they
had required an override like mine did, more would have got the
message.
I tried following code:
int foo() { return 1; }
Both MSVC and clang warn about it at high warnings level (-Wall for
MSVC, -Wpedantic for clang). But they dont warn at levels that most
people use in practice (-W3 or -W4 for MSVC, -Wall for clang).
gcc13 produces no warning even at -Wpedantic. It does produce
warning with '-Wpedantic -std=xxx' for all values of xxx except c23
and gnu23. The absence of warning for c23/gnu23 makes sense, the
rest of gcc behavior - less so.
gcc -Wpedantic makes very little sense without specifying a C
standard (rather than a gnu C standard).
But why would you expect a warning from code that is perfectly legal
and well-defined C code, without explicitly enabling warnings that
check for particular style issues? Non-prototype function
declarations are deprecated (since C99), but not removed from the
language until C23 (where that declaration is now a function
prototype).
I expect warning at -Wall, because it is deprecated. Those who do
not want warning can turn it off explicitly with -Wno-strict-prototypes
or whatever the name of the switch.
On 03/07/2024 15:41, DFS wrote:
On 7/3/2024 5:36 AM, bart wrote:
That's enough of a track record for even one person that one can say,
Linux pretty much always comes with gcc. And if it doesn't, it's easy
to install as you say.
distrowatch.com shows most distros come with gcc preinstalled.
No, it does not.
Distrowatch shows the version of the packages in the
distributions repositories,
not what is installed by default.
And almost all distributions will have gcc available.
I think Windows should come with various development tools and
programs preinstalled and ready to go: tcc, python, VS Code, SQLite.
Python would be useful to have by default on Windows. The rest, not so much.
On 7/4/2024 4:24 AM, David Brown wrote:
On 03/07/2024 15:41, DFS wrote:
On 7/3/2024 5:36 AM, bart wrote:
That's enough of a track record for even one person that one can say,
Linux pretty much always comes with gcc. And if it doesn't, it's easy
to install as you say.
distrowatch.com shows most distros come with gcc preinstalled.
No, it does not.
Yes, it does.
DFS <guhnoo-basher@linux.advocaca> writes:
On 7/4/2024 4:24 AM, David Brown wrote:
On 03/07/2024 15:41, DFS wrote:
On 7/3/2024 5:36 AM, bart wrote:
That's enough of a track record for even one person that one can say, >>>>> Linux pretty much always comes with gcc. And if it doesn't, it's easy >>>>> to install as you say.
distrowatch.com shows most distros come with gcc preinstalled.
No, it does not.
Yes, it does.
David is correct. I just installed Fedora41 and there were no
development tools (compilers, devel libraries, binutils, gdb,
make) installed by default (preinstalled).
The end-user is required to install them manually.
DFS <guhnoo-basher@linux.advocaca> writes:
On 7/4/2024 4:24 AM, David Brown wrote:
On 03/07/2024 15:41, DFS wrote:
On 7/3/2024 5:36 AM, bart wrote:
That's enough of a track record for even one person that one can say, >>>>> Linux pretty much always comes with gcc. And if it doesn't, it's easy >>>>> to install as you say.
distrowatch.com shows most distros come with gcc preinstalled.
No, it does not.
Yes, it does.
David is correct. I just installed Fedora41 and there were no
development tools (compilers, devel libraries, binutils, gdb,
make) installed by default (preinstalled).
The end-user is required to install them manually.
On 7/4/2024 4:24 AM, David Brown wrote:
On 03/07/2024 15:41, DFS wrote:
On 7/3/2024 5:36 AM, bart wrote:
That's enough of a track record for even one person that one can
say, Linux pretty much always comes with gcc. And if it doesn't,
it's easy to install as you say.
distrowatch.com shows most distros come with gcc preinstalled.
No, it does not.
Yes, it does.
Distrowatch shows the version of the packages in the distributions
repositories,
Wrong again.
From the founder of distrowatch:
"The package versions are the ones included on the install media."
On 1/3/2025 7:48 AM, David Brown wrote:
On 02/01/2025 19:16, DFS wrote:
On 7/4/2024 4:24 AM, David Brown wrote:
On 03/07/2024 15:41, DFS wrote:
On 7/3/2024 5:36 AM, bart wrote:
That's enough of a track record for even one person that one can
say, Linux pretty much always comes with gcc. And if it doesn't,
it's easy to install as you say.
distrowatch.com shows most distros come with gcc preinstalled.
No, it does not.
Yes, it does.
No.
You were wrong half a year ago when this discussion was active, and
you are still wrong now. Are you /really/ bearing a grudge for that
long?
My experience in the past was gcc was almost always installed with the distro.
Distrowatch shows the version of the packages in the distributions
repositories,
Wrong again.
 From the founder of distrowatch:
"The package versions are the ones included on the install media."
On 02/01/2025 19:16, DFS wrote:
On 7/4/2024 4:24 AM, David Brown wrote:
On 03/07/2024 15:41, DFS wrote:
On 7/3/2024 5:36 AM, bart wrote:
That's enough of a track record for even one person that one can
say, Linux pretty much always comes with gcc. And if it doesn't,
it's easy to install as you say.
distrowatch.com shows most distros come with gcc preinstalled.
No, it does not.
Yes, it does.
No.
You were wrong half a year ago when this discussion was active, and you
are still wrong now. Are you /really/ bearing a grudge for that long?
Distrowatch shows the version of the packages in the distributions
repositories,
Wrong again.
 From the founder of distrowatch:
"The package versions are the ones included on the install media."
Re-read that sentence. Then try again a few more times, until you understand it. Having a package on the install media does /not/ mean it
is necessarily installed
- it merely means it is available for
installation if the user wants. In most cases, people do not install anything close to all the packages on the installation media (unless the installation media is intentionally for a minimal install).
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 546 |
Nodes: | 16 (1 / 15) |
Uptime: | 159:59:49 |
Calls: | 10,385 |
Calls today: | 2 |
Files: | 14,056 |
Messages: | 6,416,492 |