LWN.net Logo

Day: GNOME OS

Day: GNOME OS

Posted Aug 8, 2012 16:53 UTC (Wed) by mathstuf (subscriber, #69389)
In reply to: Day: GNOME OS by juliank
Parent article: Day: GNOME OS

So…what browser do you use? uzbl is C, but webkit dwarfs its size and is C++. dillo? w3c? elinks?


(Log in to post comments)

Day: GNOME OS

Posted Aug 8, 2012 17:00 UTC (Wed) by juliank (subscriber, #45896) [Link]

Unfortunately, some software is written in C++, so we can't live C++-free. But that's not a reason to write even more software in it. There are several reasons for this:

* Fragile ABI. libstdc++ ABI is partially different when using -std=c++11, so combining C++11 code bases with older code bases is fragile.

* Build time explosion. The extreme use of inline code and templates causes an increase in build times (especially if you use boost stuff or STL).

There are probably other reasons to avoid C++ when reasonably possible, but I don't want to continue writing this comment.

Day: GNOME OS

Posted Aug 8, 2012 17:59 UTC (Wed) by Cyberax (✭ supporter ✭, #52523) [Link]

libstdc++ ABI is being addressed. It's already backwards-compatible, but not very developer-friendly for the new code.

Build time of QT-based software is not significantly greater than GTK-based software.

Day: GNOME OS

Posted Aug 8, 2012 23:29 UTC (Wed) by Company (guest, #57006) [Link]

I am sorry?

C++ compilers are orders of magnitude slower and more memory-intensive than C compilers.

http://www.phoronix.com/scan.php?page=news_item&px=MT... builds Linux in less than 1 minute on a single core. A Firefox (which is less code size) build according to Firefox's build farm at https://tbpl.mozilla.org/ takes from slightly less than an hour to 2 hours.

Day: GNOME OS

Posted Aug 9, 2012 0:05 UTC (Thu) by hummassa (subscriber, #307) [Link]

You just compared "You can run 5 km in two minutes in a Ferrari, but it takes more than one hour to run 30 km in a bycicle!"

Day: GNOME OS

Posted Aug 9, 2012 2:37 UTC (Thu) by Company (guest, #57006) [Link]

I'm not sure how you got to that comparison, but I'm waiting for you to prove me wrong. Go ahead.

Day: GNOME OS

Posted Aug 9, 2012 2:46 UTC (Thu) by mathstuf (subscriber, #69389) [Link]

First, that's not single *core*, but *socket* for the kernel build. Second, it's a $1050 processor. That's the Ferrari. I couldn't see what the build farm was using, but it's not /that/ good.

Better would be to compare Koji's build times for the packages (though you'll need to factor out the root.log time due to different dependencies). Bonus points for getting builds from the same host at low load.

Day: GNOME OS

Posted Aug 9, 2012 3:04 UTC (Thu) by mathstuf (subscriber, #69389) [Link]

The build farm is also running tests which I can imagine taking a long time. In fact, looking at the logs, they're using ccache which tells me that its 60 to 120 minutes of running tests which is more than the kernel can say.

Basically, your comparison is: "more" C is compiled by a top-of-the-line CPU in one minute than some random build farm hardware can test "less" C++ code. Never mind that the build farm builds also start by doing lots of PyPI installs (mostly cached) whereas the kernel build goes straight to building stuff.

Day: GNOME OS

Posted Aug 9, 2012 21:05 UTC (Thu) by ibukanov (subscriber, #3942) [Link]

Build farm is slow. On a 4-core Linux desktop (Core i5-2400 CPU @ 3.10GHz) Firefox builds in about 15-20 minutes depending on the build configuration. But I second the observation that extensive use of c++ makes things much slower.

SpiderMoneky, the JavaScript engine in Firefox, used to be written in C. The compilation of JS shell (that compiled only the engine without any other Firefox code) to test changes to the engine was fast. It was possible to develop it even on a netbook as the shell compiled under a minute there. Then the code switched to C++ and the build time deteriorated as more and more C++ features started to be used. In a less than a year one could forget to use netbook for any productive development and even using not the latest and greatest notebooks became problematic.

Day: GNOME OS

Posted Aug 9, 2012 23:48 UTC (Thu) by mathstuf (subscriber, #69389) [Link]

I agree that C++ is slower to compile, but as I said elsewhere:

> As for build times, yes, it's higher, but I don't really notice that much of a practical difference and what difference there is is well worth the extra safety the code has.

Unfortunately, a fair comparison can't be made without ensuring at least feature parity between the C and C++. You also have to compare bug counts and code ease-of-use (for users of the code/APIs, developers, and maintainers) and in this, C++ is a big win IMO.

The C++ SpiderMonkey has more features today than it used to have (I expect) and you have to weigh how long it took to code those features versus how long it would have taken with the C codebase to get the same features against the increased build times.

As for using a netbook, I don't know what my limits for patience would be anymore. After using my i7 and Xeon machines at work, even my Core 2 Duo was getting me impatient with builds. I don't do much beyond script-level stuff (usually Haskell, shell, or Python) or minor web development on the netbook anymore mainly due to the tiny screen (my terminals at work are 319 wide and 88 tall and netbooks just don't fit 3 80-wide Vim windows plus NERDTree on them at readable font sizes).

Day: GNOME OS

Posted Aug 10, 2012 10:38 UTC (Fri) by jwakely (subscriber, #60262) [Link]

A large part of slower C++ build times is in the linker, not just the compiler. Using Gold makes a big difference.

Day: GNOME OS

Posted Aug 10, 2012 20:05 UTC (Fri) by ibukanov (subscriber, #3942) [Link]

Surely C++ brought a lot of nice things like templates and destructors for automated cleanup significantly simplifying the code in SpiderMonkey. However, a significant compilation time increase also meant that hardware that developers use is way beyond capabilities of the most computers where Firefox runs. So it is much harder to extrapolate the effect of changes that looks nice on fastest CPU during development to the hardware that users will face.

Day: GNOME OS

Posted Aug 8, 2012 18:30 UTC (Wed) by mathstuf (subscriber, #69389) [Link]

As someone who likes coding guarantees with the language rather than logic (Haskell is nice in this regard, but I'm still mainly doing C++), C can't help in many places. Sure, there are ways to enforce things socially with code reviews and such, but it's time consuming to check stuff when I can have the compiler do most of that work for me. C-style casting is also no substitute for static_cast and dynamic_cast.

I do agree that C++ has warts (mainly where they tried to be compatible with C…and didn't quite make it[1]). Not specifying an ABI was silly (an FFI would have been much better). Common stuff is finally in the standard (much is also just boost:: -> std:: moves, so migration once we support C++11 more widely is largely just a rename in a bunch of typedefs in the codebase).

As for build times, yes, it's higher, but I don't really notice that much of a practical difference and what difference there is is well worth the extra safety the code has. It also helps to put most of the heavy Boost template magic in its own source file helps to minimize rebuilding of that file (e.g., the Boost.Spirit grammar in its own file (getting flex/bison working on Windows is *lots* of fun…I'll take Boost TYVM)).

[1]A fun one:

struct A { A(int) { /* … */ } int a; };
typedef float B;
int main(int argc, char**) { A a = (A)argc; B b = (B)argc; }

The A ctor gets called here where B is a C-style cast.

Day: GNOME OS

Posted Aug 8, 2012 20:20 UTC (Wed) by nix (subscriber, #2304) [Link]

I don't see how that's an incompatibility with C. struct A has a constructor, so it's not a POD type and can clearly not exist in C at all.

I'd not call implicitly calling constructors on casts to be much of a wart: if you didn't call the constructor, you'd end up with a non-initialized object and break things. The only alternative (as implemented if you declare the constructor explicit) is to ban a cast in that situation entirely, which means you make the casts to A and B look different merely because one is a POD type and the other is not, which is an implementation detail which the users of the types should not have to know.

Implicit conversions *are* full of horrible warts (such as the crudeness of the no-implicit-conversion-chains rule and *everything* about the syntax of 'operator random-typename'), but this is not one of them.

Day: GNOME OS

Posted Aug 8, 2012 20:30 UTC (Wed) by mathstuf (subscriber, #69389) [Link]

It's not a compatibility with C issue, but it happens because C++ tried to be fully C compatible. If you're doing C casts in a template or something, it acts differently based on whether the template type is POD or not. If C++ had just said "we don't support C casts" this wouldn't be an issue. Plus, if you do rely on C casts for some (C++ POD) struct for some reason, you need to document the struct that it needs to stay a POD struct.

I really would have liked 'implicit' to be the keyword rather than 'explicit' as well, but alas…

Day: GNOME OS

Posted Aug 8, 2012 23:01 UTC (Wed) by nix (subscriber, #2304) [Link]

I think everybody agrees with you on that last point (and perhaps similarly for 'virtual', though changing that to 'nonvirtual' would violate the 'you don't pay for what you don't use' principle, so perhaps not), but such is the backward-compatibility burden...

Day: GNOME OS

Posted Aug 8, 2012 23:47 UTC (Wed) by mathstuf (subscriber, #69389) [Link]

Not sure I feel the same about virtual because of the "only pay for what you use" principle. Another thing: something like a 'delayed const' (similar to 'final' in Java IINM) so that you can modify a variable and then 'constify' it so that it doesn't change after that point (something the compiler could enforce rather than assignment to a const& and relying on people to not use the pre-const& variable after).

Day: GNOME OS

Posted Aug 10, 2012 7:49 UTC (Fri) by nix (subscriber, #2304) [Link]

The 'delayed const' sounds like a finer-grained 'mutable'.

(But don't mention Java. Java's lack of constness is *awful*. More than once I have introduced horrible bugs because I accidentally modified a hash key due to the silent aliasing and lack of const of java.util.Map -- meanwhile such bugs never ever happen in the STL, not due to its nifty space-age genericity, but simply because its data structures copy the types handed into them, and won't give you something back that shouldn't be modified without a const on it. For that matter I have written data structures in poor old crude C with the same 'always copy, use const' rules as the STL, and *they* never suffered from this either.)

Day: GNOME OS

Posted Aug 10, 2012 8:10 UTC (Fri) by jezuch (subscriber, #52988) [Link]

> But don't mention Java. Java's lack of constness is *awful*.

Yes, that's one of the very few features that I truly miss in Java. There are workarounds like defensive copies and immutable wrappers but they're no fun.

Day: GNOME OS

Posted Aug 10, 2012 17:42 UTC (Fri) by mathstuf (subscriber, #69389) [Link]

Also typedefs. I hated using Strings for everything and 5 parameters all of String to Android APIs means having to look up what the order is. At least the ordering is consistent where I used it (unlike, e.g., PHP)

Day: GNOME OS

Posted Aug 10, 2012 10:57 UTC (Fri) by jwakely (subscriber, #60262) [Link]

If C++ hadn't supported C casts (or had used a FFI for C interop, as you suggested above) it would never have achieved the success it enjoys today, which only happened by building on C's popularity and success. C compatibility is sometimes a millstone around the neck of C++ now, but without it this discussion probably wouldn't even be happening.

Without supporting C-style casts you couldn't write something as simple as this and have it be valid in both C and C++:

  int* p = (int*)malloc(n*sizeof(int));
It's the right design for a C-style cast to invoke a user-defined conversion if one exists, for the reasons nix gives. Why would you want to use C-style casts in templates anyway? Code in templates doesn't need to be C-compatible. You can't cast between arbitrary POD types anyway, in C or C++. Can you give an example that shows what you mean?

Day: GNOME OS

Posted Aug 10, 2012 11:09 UTC (Fri) by hummassa (subscriber, #307) [Link]

You can't c-cast from a POD type to another, but you can c-cast from a pointer-to-any-type to another (even if you have to cast to void* in the middle).

Day: GNOME OS

Posted Aug 10, 2012 11:18 UTC (Fri) by jwakely (subscriber, #60262) [Link]

Was mathstuf's statement "it acts differently based on whether the template type is POD or not" talking about casting pointers?

Day: GNOME OS

Posted Aug 10, 2012 14:59 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link]

You can always do:
>int *p = reinterpret_cast<int*>(malloc(n*sizeof(int))

Day: GNOME OS

Posted Aug 10, 2012 15:51 UTC (Fri) by jwakely (subscriber, #60262) [Link]

How would that be valid C?

Day: GNOME OS

Posted Aug 10, 2012 16:54 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link]

It's not, and that's the point. C++ could have avoided lots of warts caused by C-compatibility without losing in functionality.

Day: GNOME OS

Posted Aug 8, 2012 20:16 UTC (Wed) by nix (subscriber, #2304) [Link]

* Fragile ABI. libstdc++ ABI is partially different when using -std=c++11, so combining C++11 code bases with older code bases is fragile.
Jonathan Wakely pointed out recently that this is not true as of G++ 4.8: this has been backported to GCC 4.7.2+ as well (making 4.7.1's C++11 ABI incompatible with 4.7.2's, but anyone expecting a stable C++11 in GCC 4.7, the first version to have C++11 support at all, is living in a fantasy world in my opinion).

Day: GNOME OS

Posted Aug 9, 2012 15:22 UTC (Thu) by arafel (subscriber, #18557) [Link]

Maybe. I'm not convinced it's an unrealistic desire to retain compatibility across minor version changes, personally - if you're breaking the ABI then don't call it 4.7.x.

But I try hard not to use C++, so from a personal point of view it doesn't affect me that much. ;-)

Day: GNOME OS

Posted Aug 9, 2012 19:45 UTC (Thu) by mathstuf (subscriber, #69389) [Link]

Since a minor version bump is more likely to be done in a "stable" distro, fixing 4.7 so that it's compatible with other version series is likely better than keeping 4.7.x incompatible forever. Of course, this only matters when -std=c++11 is in effect, so the problem is unlikely to manifest unless 4.7.1 is the last release in some popular EL distro.

Day: GNOME OS

Posted Aug 10, 2012 15:22 UTC (Fri) by slashdot (guest, #22014) [Link]

Wow, awesome.

Thank god that there are still some sane people in this world.

When some idiot from GCC announced that they wouldn't even try to keep a compatible ABI, I thought the GNOME3 disease had taken hold over there too, and all hope was lost, and it's great to hear the outbreak has instead been contained.

I mean, being able to compile any subset of a C++98 program as C++11 is an absolutely essential feature for obvious reasons, and not being able to use, say, foreach or auto without changing a program's ABI would be totally insane.

Day: GNOME OS

Posted Aug 10, 2012 15:44 UTC (Fri) by mathstuf (subscriber, #69389) [Link]

The standard actually changed the ABI for std::string and std::list (possibly some others). The fix involves adding an attribute to help choose between the new and old ABI versions of classes. I can't find the blog link I read that on right now though.

From [1]:

> GCC versions 4.7.0 and 4.7.1 had changes to the C++ standard library which affected the ABI in C++11 mode: a data member was added to std::list changing its size and altering the definitions of some member functions, and std::pair's move constructor was non-trivial which altered the calling convention for functions with std::pair arguments or return types. The ABI incompatibilities have been fixed for GCC version 4.7.2 but as a result C++11 code compiled with GCC 4.7.0 or 4.7.1 may be incompatible with C++11 code compiled with different GCC versions and with C++98/C++03 code compiled with any version.

[1]http://gcc.gnu.org/gcc-4.7/changes.html

Day: GNOME OS

Posted Aug 10, 2012 15:58 UTC (Fri) by jwakely (subscriber, #60262) [Link]

> The standard actually changed the ABI

No. The standard doesn't mention an ABI.

Some implementations' std::string and std::list have always been compatible with the new requirements, so don't have to change.

So more accurately, the C++11 standard requires certain properties of std::string and std::list which are incompatible with GCC's existing implementations of those types.

> I can't find the blog link I read that on right now though.

Maybe you mean my comment that nix refers to in the grandparent post?

Day: GNOME OS

Posted Aug 10, 2012 16:08 UTC (Fri) by mathstuf (subscriber, #69389) [Link]

Ah, that makes more sense.

And yes, that blog post. Thanks :) .

Day: GNOME OS

Posted Aug 10, 2012 16:01 UTC (Fri) by jwakely (subscriber, #60262) [Link]

There was never a question of foreach or auto changing the ABI, the incompatibilities are restricted to the library. Try to understand the facts before spouting rubbish and calling people idiots.

That idiot might be the same person who reported the news you applaud now. You're welcome by the way. Now when are you going to do something for me in return other than lower the level of discourse on LWN?

Day: GNOME OS

Posted Aug 10, 2012 17:02 UTC (Fri) by slashdot (guest, #22014) [Link]

Except that I'm pretty sure auto or foreach required --std=c++11 to be used, which also resulted in some macros getting defined (__GXX0X_EXPERIMENTAL__ or something like that), which in turn changed the size of std::list in the STL headers due to an #ifdef.

As far as I can tell, this is what they fixed in GCC 4.7.2 (apparently by reverting the changes, with a plan to make it a separate switch along with the ability of C++98 and C++11 ABIs to coexist), and the rubbish is the one you just spouted.

I'm not sure who the "idiot" was, but I remember reading in GCC bugzilla someone who argued that the situation described above was totally fine, while any reasonable person would instead think that it had to be avoided at any cost, as they fortunately did later.

Obviously someone who does that definitely deserves to be insulted, since he first insulted and damaged all its users with such a decision.

Day: GNOME OS

Posted Aug 10, 2012 17:25 UTC (Fri) by nix (subscriber, #2304) [Link]

Sheesh. You just don't take a hint, do you? The implementors of all this stuff - the mysterious impersonal 'they' you refer to -- are Paolo Carlini and Jon Wakely (y'know, the guy you're responding to). Neither of them are any sort of idiot, though I suspect from your failure to notice the authorship of these patches despite having received multiple direct links to them that *you* might need a major upgrade of your observational skill.

Day: GNOME OS

Posted Aug 10, 2012 17:38 UTC (Fri) by slashdot (guest, #22014) [Link]

Well, definitely they were idiots when they introduced the ABI change in question and defended it on Bugzilla etc.

Which is really hard to argue against, since they then had to revert the change in the middle of a stable series!

Anyway, I guess the important thing is that they returned to sanity, although obviously it would have been better for that to happen before releasing 4.7.0.

Day: GNOME OS

Posted Aug 10, 2012 17:50 UTC (Fri) by slashdot (guest, #22014) [Link]

BTW, the REAL idiots here are the guys in the C++ comittee who released a broken unimplementable standard (or alternatively, a standard without a full compatibility goal, which is even worse), despite having had 13 (!!!) years to fix it.

The gcc developers pretty much merely slavishly followed that idiocy without questioning, until they realized their mistake.

Day: GNOME OS

Posted Aug 10, 2012 18:30 UTC (Fri) by nix (subscriber, #2304) [Link]

Er, you do realise that the C++ Standard, following the original STL, has imposed time and space complexity constraints on various parts of the library for a very long time? They're essential, because those constraints are the only difference between some of the Standard's data structures.

This was just a new constraint, which was unfortunately incompatible with the existing implementation of the list<> in GCC, and it was impossible to change it without breaking backward compatibility. (One problem with templated data structures is that a lot of things you wouldn't expect to be ABI concerns actually are, because they are included in programs using them via template expansion.)

Deciding whether to violate the language standard or piss off your users is an unpleasant fork to be in -- but it's not the committee's fault either, because this sort of change is what language standard revisions have always done. C99 broke some valid C89 code: C11 breaks some more. It's just that the set of GCC-compiled code that got broken by a fully conformant implementation of the C++11 list<> was rather large...

Day: GNOME OS

Posted Aug 10, 2012 19:13 UTC (Fri) by slashdot (guest, #22014) [Link]

> This was just a new constraint, which was unfortunately incompatible with the existing implementation of the list<> in GCC, and it was impossible to change it without breaking backward compatibility

And that's the problem.

Adding the new constraint by the C++ committee was simply asinine, especially, since you lose O(1) list splicing (and you can keep the size yourself with C++98 std::list, but can't do O(1) splice yourself with C++11 std::list), and because at least one existing implementation could not provide it while keeping compatibility.

They should have added a new type if they wanted C++ to have a linked list with O(1) size().

BTW, they also broke multithreaded programs using std::list, since unless the size field is updated with atomics (which kills performance on several archs), it's no longer true that you can add to the head of a non-empty list in a thread and to the tail in another thread, which would work in C++98 libstdc++.

As for the GCC, I think it should need a separate option to enable ABI-breaking C++11 changes, and --std=c++11 should only enable the backwards compatible C++11 subset, which appears to be what they hint at in the recent announcement.

C++11 is not fully implemented anyway, so that's not an issue for now, and perhaps in the meantime the standard can be revised to revert the changes.

Day: GNOME OS

Posted Aug 10, 2012 19:28 UTC (Fri) by juliank (subscriber, #45896) [Link]

If I had to guess, I'd say that the O(1) size() thing was introduced to the standard by Microsoft.

Day: GNOME OS

Posted Aug 10, 2012 19:42 UTC (Fri) by juliank (subscriber, #45896) [Link]

OK, it seems to be pushed by Apple via proxy, not Microsoft, as far as I can tell.

Day: GNOME OS

Posted Aug 10, 2012 20:02 UTC (Fri) by foom (subscriber, #14868) [Link]

Slashdot: You've been told more than once to stop with such insulting. It is exceedingly inappropriate. Maybe it's expected behavior on your namesake website, but not here.

The change was a mistake, the defense of it was wrong. That STILL doesn't mean you get to call the people involved idiots.

Day: GNOME OS

Posted Aug 10, 2012 17:30 UTC (Fri) by ris (editor, #5) [Link]

> Obviously someone who does that definitely deserves to be insulted, since > he first insulted and damaged all its users with such a decision.

It is not at all obivious that anyone needs to be insulted just because they do something you disagree with. Please refrain from insulting people on this site. This is your second warning.

Day: GNOME OS

Posted Aug 10, 2012 17:21 UTC (Fri) by nix (subscriber, #2304) [Link]

I do wonder if there's anyone on Earth slashdot won't call an idiot or a moron. There certainly doesn't seem to be any need for actual evidence before accusations are launched.

Day: GNOME OS

Posted Aug 13, 2012 11:33 UTC (Mon) by nye (guest, #51576) [Link]

>I do wonder if there's anyone on Earth slashdot won't call an idiot or a moron. There certainly doesn't seem to be any need for actual evidence before accusations are launched.

But it's the open source way, and is widely (though not universally) supported here whenever the question comes up of whether this is an appropriate way to behave.

Standards are great, double standards doubly so.

(BTW I'm not being flippant - this is exactly the standard of behaviour that's considered normal and expected in the open source communities I look at. Compared to debian-devel it's positively gentlemanly.)

Day: GNOME OS

Posted Aug 13, 2012 16:39 UTC (Mon) by apoelstra (subscriber, #75205) [Link]

> But it's the open source way, and is widely (though not universally) supported here whenever the question comes up of whether this is an appropriate way to behave.

I'm sure you could find many examples of open-source communities where rudeness and flamefests are considered appropriate behaviour. You could also find examples where the opposite is true.

But however "widely supported" this attitude is in the greater open source world, it is my experience that it's not supported here on LWN, which is (for the most part) a very polite, civil, intelligent place for discussion.

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds