LWN.net Logo

Sobotka: Why GIMP is inadequate

Sobotka: Why GIMP is inadequate

Posted Jan 12, 2011 15:15 UTC (Wed) by HelloWorld (guest, #56129)
In reply to: Sobotka: Why GIMP is inadequate by cmccabe
Parent article: Sobotka: Why GIMP is inadequate

The C versus C++ thing has been discussed to death before. Read Linus Torvalds' take on it. He's not very diplomatic, but he is right. In short, object orientation isn't a language feature; it's a programmer feature.
This is a bogus argument for two reasons. Firstly, C++ does not equal C+OOP. Even if C++ didn't have any support for OOP, it'd still be worth using because of features like templates, namespaces, RAII and all that. Secondly, an object-oriented design will look much, much cleaner and be more maintainable in C++ than in C.


(Log in to post comments)

Sobotka: Why GIMP is inadequate

Posted Jan 13, 2011 10:17 UTC (Thu) by paulj (subscriber, #341) [Link]

C may have limitations and deficiencies relative to modern programming concepts - I could accept that. However, how does it follow that the answer to this is C++, as the original commentator suggests? C++ perhaps has *even more* deficiencies than C, relative to modern programming concepts and other (often necessarily more recent implementations)? Let's look at your list:

Templates: These are a bodged implementation of generic/meta types (perhaps not C++'s fault, as generic/meta types were prototyped in C++ to an extent). Due to different instantiations of the same template literally copying the code, they're hell on I-caches - spectacularly inefficient. Due to its implementation roots as code that's inserted in a pre-processor phase, producing compilation error messages that don't look like incomprehensible gobbledygook to anyone but C++ compiler developers and/or language spec committee members can be challenging. At least one widely used C++ compiler still fails terribly at this.

RAII: This is a programming pattern popularised, in large part, because of the *deficiencies* of C++, wrt the many subtle ways exceptions interact with other parts of the C++ language spec (construction and deconstruction particularly). Further, you *can* quite easily (if you're adhering to OOP) do RAII in C, as I'm sure you must know.

Namespaces: Ok, I grant you that one. But there are other choices of language, beside C++, with namespacs. ;)

Then there are all the other problems with C++...

So, again, if you got fed up with C and wanted to switch to a better language for some large, high-level user-space project (e.g. GUI graphics processing app), why on earth would you choose C++? Surely C#, Java, or Vala, perhaps others, would be a much better choice? For the low-level, C beats C++. For the high-level, with the rise of much cleaner languages that have learned from C++ mistakes and have not been saddled by its baggage, has C++ not had its day?

Sobotka: Why GIMP is inadequate

Posted Jan 13, 2011 11:33 UTC (Thu) by boudewijn (subscriber, #14185) [Link]

"However, how does it follow that the answer to this is C++, as the original commentator suggests?"

Where did I suggest that? A big C project that uses GObject is awfully difficult to get into for a newbie.

Heck, I have spent more than once several weeks getting people up to speed with Qt and C++ so they could contribute to Krita (and C++ with Qt is awfully close to Java for a beginner) so I know that "C++" isn't the answer. I think there is no answer for Gimp -- but that doesn't mean it isn't a problem.

Spending that time on beginners has almost always been worth it, by the way, with the newcomers becoming valued members of the development team and producing awesome stuff.

Sobotka: Why GIMP is inadequate

Posted Jan 19, 2011 21:36 UTC (Wed) by DOT (subscriber, #58786) [Link]

"Heck, I have spent more than once several weeks getting people up to speed with Qt and C++ so they could contribute to Krita (and C++ with Qt is awfully close to Java for a beginner) so I know that "C++" isn't the answer. I think there is no answer for Gimp -- but that doesn't mean it isn't a problem."

Since Vala is embarassingly compatible with C and GObject, it should be possible to write new code in that language where appropriate.

But honestly, I think the problem is not in the code. You'll only have to look at LibreOffice and its awesome community to know that code doesn't really matter. I would start looking for the problem somewhere in human department.

Sobotka: Why GIMP is inadequate

Posted Jan 13, 2011 11:53 UTC (Thu) by HelloWorld (guest, #56129) [Link]

> C may have limitations and deficiencies relative to modern programming concepts
That seems to be an understatement ;)

> Templates: These are a bodged implementation of generic/meta types
They're not. Stroustrup knew about ML (which had generics all along) when he designed C++, but he deliberately designed templates differently. ML-style generics require a boxed data representation and can't properly deal with stuff like overloaded assignment operators, and you can't specialize them. Templates and generics are two very different beasts, even though they serve similar purposes.

> Due to different instantiations of the same template literally copying the code, they're hell on I-caches - spectacularly inefficient.
They're not, actually. Try sorting a million floating point numbers with std::sort and qsort. The std::sort version will be much faster, because in a function template, the comparison can be inlined, while in the qsort version, you have to call it through a function pointer, defeating the CPU's branch prediction.

Also, partial template specialization can be (and is being) used to reduce or eliminate copied code. For example, it is possible to specialize the vector<T> class so that if T is a POD type (POD = plain old data), a generic implementation based on memcpy etc. will be used and the template merely acts as a type-safe wrapper around it, the overhead of which can be trivially optimized away by the compiler.

> Due to its implementation roots as code that's inserted in a pre-processor phase, producing compilation error messages that don't look like incomprehensible gobbledygook to anyone but C++ compiler developers and/or language spec committee members can be challenging.
Cfront never was any sort of preprocessor, it always was a proper compiler which just happened to generate C code as that was the only way to achieve good portability back then.
I agree that template error messages are a problem, but it's not an easy one to fix. The problem is that the compiler can't know if a failed template instantiation is due to a bug in the template or due to the type parameter not satisfying the requirements of the template.

In Haskell, type classes solve a similar problem fairly elegantly. They tried to add a similar feature to C++0x but failed, so this problem will be with us for some time.
> RAII: This is a programming pattern popularised, in large part, because of the *deficiencies* of C++, wrt the many subtle ways exceptions interact with other parts of the C++ language spec (construction and deconstruction particularly).
Every language needs to deal with some form of resource cleanup, and RAII is a very elegant way to do so. The fact that one motivation for RAII was exception safety doesn't change that in the least. What other solution for the resource cleanup problem do you propose? A GC doesn't count as it only deals with memory. I found the "finally" blocks found in many languages to be much less useful.

> Further, you *can* quite easily (if you're adhering to OOP) do RAII in C, as I'm sure you must know.
As I'm sure you must know, there is no such thing as an implicitly called destructor in C. This makes the idiom much less useful than it is in C++.

> So, again, if you got fed up with C and wanted to switch to a better language for some large, high-level user-space project (e.g. GUI graphics processing app), why on earth would you choose C++? Surely C#, Java, or Vala, perhaps others, would be a much better choice?
Hey, I didn't propose to rewrite the Gimp in C++, did I? Anyway, comparing C# etc. to C++ is a red herring. C++ is a systems programming language, and it was always meant to be. Which leads us to the next point...

> For the low-level, C beats C++.
I disagree. Everything you can do in C can also be done in C++, and it'll be cleaner and more elegant. In fact, I flat-out hate C. It needs to die a gory death, and the sooner that happens, the better. It just doesn't do what I need it to do, not even for low-level programming.

Sobotka: Why GIMP is inadequate

Posted Jan 14, 2011 9:31 UTC (Fri) by paulj (subscriber, #341) [Link]

Re templates: I don't know enough about the history of C++, but that to me sounds like C++ settled for a bodged version of generics because of implementation compromises. I'm not sure what you mean by 'specialise', do you mean extend the base functionality, or modify/remove it? If the former, generic type theory allows that, if latter then that's no longer safe according to standard type-theory, no (but then templates themselves aren't really types in C++ - part of the bodge)?

Caching: What you describe is the relative efficiency of function pointers, branch-prediction v I-cache. That's not a constant thing at all and varies a lot between processors and over time as processor technology changes. E.g. there's no fundamental reason why branch-prediction can not predict branches behind repeated calls to the same function pointer - that branch predictors in the past have not dealt well with function pointers doesn't mean this always is so. On the other hand, that templates put pressure on I-caches *is* a fundamental fact. It will always be a factor, so long as CPUs need I-caches.

RAII: C doesn't explicitly have support for implicitly calling a custom per-object deallocator on free(), but setting up the scaffolding to do this is half a days work, and there are existing allocator libraries that can make this even easier (e.g. talloc). If you lack the imagination to put a header in front of your allocated objects and populate it with useful function pointers, and override free(), well.... ;) That half-days-work is much shorter than the *years* it takes to discover all the subtle ways C++'s historical baggage and design decisions can bite the programmer. ;)

As for C#, Java, Vala, etc and rewriting the GIMP: this discussion about C v C++ started because people criticised GIMP for being in C and suggested C++ would be better. Where's the evidence for this claim? Even if we accept C++ has merits over C, exactly how does this make C++ the correct choice *today* for programming large, end-user applications? If the answer isn't C, then it surely isn't C++ either...

Sobotka: Why GIMP is inadequate

Posted Jan 14, 2011 15:00 UTC (Fri) by HelloWorld (guest, #56129) [Link]

Re templates: I don't know enough about the history of C++, but that to me sounds like C++ settled for a bodged version of generics because of implementation compromises.
They're not, and I already told you why: generics are less flexible and require a boxed data representation, at least in any implementation of generics I know of. And if templates were merely a sucky replacement for generics, why did the developers of the D language choose to implement templates as well?
RAII: C doesn't explicitly have support for implicitly calling a custom per-object deallocator on free(),
It's not about calling a custom deallocator on free but about implicitly doing something (like unlocking a mutex or decreasing a refcount) when an object leaves some scope. This needs some form of language support.
<ramblings about caching>
Well, if you think that qsort offers a better tradeoff than std::sort, you can still write an easier to use, type-safe wrapper.
template<typename T> int compare(const void *, const void *);
// implementation left as an exercise for the reader

template<typename T> void my_sort(T *base, size_t nmemb) {
  return std::qsort(base, nmemb, sizeof(T), &compare<T>);
}
As for C#, Java, Vala, etc and rewriting the GIMP: this discussion about C v C++ started because people criticised GIMP for being in C and suggested C++ would be better. Where's the evidence for this claim? Even if we accept C++ has merits over C, exactly how does this make C++ the correct choice *today* for programming large, end-user applications? If the answer isn't C, then it surely isn't C++ either...
I think that reasons were given for preferring C++ to C (templates, OOP, RAII, namespaces); of course, you're free to disagree with these. I also didn't claim C++ is the right choice for an application like the GIMP if it were written today, and it probably isn't, as a low level language like C++ is probably a poor choice for a graphical app today. It merely annoys me when people like cmccabe keep trolling against C++ and do as if C were the holy grail of systems programming languages.

Sobotka: Why GIMP is inadequate

Posted Jan 14, 2011 16:29 UTC (Fri) by paulj (subscriber, #341) [Link]

Generics have a sound body of type theory behind them though. Boxing types - I don't see a problem with that for OOP. And from what you say, the error-message problem is actually somewhat fundamental to templates. I really hate templates I have to say.

Re implicit destructors for automatic variables. True, that requires language support. OTOH, C++ allowing automatic storage objects is one of those things that lead to subtle corner-cases, ISTR...

Anyway, our opinions clearly differ. ;)

Sobotka: Why GIMP is inadequate

Posted Jan 14, 2011 18:32 UTC (Fri) by HelloWorld (guest, #56129) [Link]

Generics have a sound body of type theory behind them though.
C++ templates have been studied by type theorists too, see for example this paper.
Boxing types - I don't see a problem with that for OOP.
C++ is not only object-oriented, and in fact, containers are very often used for built-in types like int. Boxing these is ridiculously inefficient.
Re implicit destructors for automatic variables. True, that requires language support. OTOH, C++ allowing automatic storage objects is one of those things that lead to subtle corner-cases, ISTR...
Like what? I always found implicitly called destructors to be a boon. Much more so than, say, Java's finally blocks. Alas, YMMV and as you already said, we should probably just agree to disagree :).

Sobotka: Why GIMP is inadequate

Posted Jan 14, 2011 20:34 UTC (Fri) by HelloWorld (guest, #56129) [Link]

> And from what you say, the error-message problem is actually somewhat fundamental to templates.
A similar problem applies to dynamically typed languages like python though. The interpreter can't possibly know whether the type of a function argument satisfies the requirements of the function it is passed to. The difference being that a C++ compiler will point that out at compile-time, while a dynamically typed language won't throw up until run-time, much less give you a sensible error message.

Poor implementations are also part of the problem. g++'s error messages are worse than they could be, for example it always talks about std::basic_string<char, std::char_traits<char>, std::allocator<char> > instead of plain std::string (the latter being a typedef for the former). Clang++ is supposed to be much better at this, though I haven't tried it yet.

Sobotka: Why GIMP is inadequate

Posted Jan 18, 2011 20:06 UTC (Tue) by daniel (subscriber, #3181) [Link]

"I really hate templates I have to say."

For me it's a love hate relationship. I love the way I can generate efficient code from terse, readable source. I hate the way compile errors get weirder and weirder, the the latter may be as much an implementation issue as anything. Templates are really just a highly automated form of cut and paste that allows you to create *maintainable* cut and paste code, and package it for general use.

The extent to which cut and paste code abuses the processor cache says more about the programmer than the mechanism. I use partially specialized templates to create efficient variant forms of low level graphical operations. The initial pure C code base I developed to do the same thing grew tendrils and degenerated to to an unmaintainable state rapidly so that working on it slowed down and became deeply unappetizing. After being recast as an orthogonal set of C++ templates the source code shrank by a multiple and I was able to add the sophisticated new capabilities that seemed only a distantly obtainable hope with the original C code base. The actual generated code hardly changed, just my ability to develop it.

Sobotka: Why GIMP is inadequate

Posted Jan 14, 2011 20:01 UTC (Fri) by cmccabe (guest, #60281) [Link]

> On the other hand, that templates put pressure on I-caches *is* a
> fundamental fact. It will always be a factor, so long as CPUs need
> I-caches.

Indeed. I'm working on a large C++ project now, and this is a big problem for us. We use the STL heavily, especially the container classes.

Incidentally, if anyone here knows some good workarounds, they would be much appreciated! I know about the void pointer trick, but unfortunately most of our containers don't contain pointers; they contain class types.

Sobotka: Why GIMP is inadequate

Posted Jan 14, 2011 13:59 UTC (Fri) by dwmw2 (subscriber, #2063) [Link]

Unconditional branches aren't so hard to predict, FWIW.

Sobotka: Why GIMP is inadequate

Posted Jan 16, 2011 21:11 UTC (Sun) by cmccabe (guest, #60281) [Link]

I wrote a little test, and apparently std::sort *is* faster than qsort, at least at sorting an array of 4 million ints. My CPU is an AMD Phenom(tm) II X4 820.

In my opinion, templates are the best feature of C++. They're really the *only* feature I miss in C-land. You can use macros to accomplish the same thing in C. I vaguely remember that the BSD kernel has a header file implementing qsort-as-a-macro. However, it's less convenient.

Sobotka: Why GIMP is inadequate

Posted Jan 17, 2011 1:11 UTC (Mon) by jthill (guest, #56558) [Link]

Glad to see somebody else sees them that way. The don't have to be all verbose and complicated, and if you collect the machinery they implement together in one spot and get the formatting right they can make things very much clearer.

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