2023-10-22

C++ slower than Java: the danger of AI, or HS

Once in a while I look up articles about programming languages, just to waste a little bit of precious time or to find inspiring quotes agreeing with my fact-grounded truth about languages which suck, despite being widely used, and those that could rule half the world, if only programming hadn’t become like modern music and art: coloured tasteless shit put inside glossy glassy windows which by mirroring attract schools of self-admired empty hedonistic puppets, once persons, playing the assigned role of the rebels, faux as a golden hole, happily in chains hidden under a silky furry trendy carpet — and the so-called artist, who’s built this captivating dreamy reality to help the rulers keeping the rabble in line, has the pockets packed of money. Burnt youth whom the awful truth can’t be revealed to — just to cite the poet.

I began writing this article on 18 September 2022. It was a filler then, it is a filler now. But this doesn’t mean that there can’t be wisdom between the lines.

Now that the mood is properly set, let’s take a look at a ridicolous article. Please do not click the link, unless you want to be spammed: truth be said, too many corners of the easy-going web has been conquered by the same spidery evil forces which control the unidirectional communication flow from “them” to “us”. Artificial so-called intelligence (which is indeed artificial, but not intelligent at all) is one of the tool which makes it possible for them not to drop one single sweat drop while they continue in the giant effort of holding the reins of billions of souls — that, and voluntary slavery.

The article’s author is Veda AI, and I suspect this is really a software, not a person. I suspect this software harvested tons of informations from programming sites, made connections and relationships between words, and produced an article which could seem to be written by an actual person, except for the fact that a person writing an article about technology wouldn’t do errors like those, would she?

Be warned: it seems the article exists as click-bait, because you’ll be hit by ads and so on. Click and look at your own risk (or protect yourself with glorious tools…)

C++

C++ is not considered a shiny modern programming language.

It is not? By whom?

But it’s still in wide use today and had to be included in the list

But what? It’s a luck it is widely used. … And now, brace youself!

It’s significantly slower than Java, though not as bad as Scala.

Is she saying Scala is the slowest, then C++, and then comes Java, which is the fastest?

In the worst (for C++) scenario, Java will run as fast as C++. But there’s no way a native executable produced by a modern compiler targeting the hardware appropriately1 can be beaten by the same code2 written in Java and running in the JVM. With JIT compiling witchcraft, in the worst (for C++) scenario they run at the same pace.

Java

Java runs on top of Java Virtual Machine, which is notorious for its slow startup times

But C++, which doesn’t run on top of any virtual machine, was slower…?

Very likely this slow startup times is an outdated fact. But even if it were a current problem, it would be irrelevant in almost all practical cases.

Java was designed in the era of single-core computing and like C++3 has only rudimentary concurrency support.

Many languages were designed in the era of single-core computing. But this doesn’t mean much, also because used programming languages change over time: nowadays Java isn’t as it was at the beginning. Concurrency, parallelism, and multithreading are old topics, existing before humans were able to make multicores CPUs.

In my opinion, many languages get concurrency wrong, even if they are “modern”. I think good ways are those used in languages like Ada, Erlang, Go, Raku,4 and surely other languages I don’t know or that slipped my mind right now.

However, I don’t know what qualifies as rudimentary concurrency support… but I suppose the same criteria can be applied to many other languages to judge them in the same way. Something like the pthread library is rudimentary when compared to what languages like Go, Erlang or Ada have (I am quite sure Ada was designed before multicores existed, too, and CSP isn’t exactly a new thing).

Currently Java has “modern” gears for easy (easier?) concurrency (if such a thing exists), and it is surely able to exploit multicores (with the help of the JVM, of course).

Beyond supporting explicit usage of threads, locks, atomic variables, concurrent-safe containers, … it also has features like future, parallelStream… And then of course frameworks like Akka5

Haskell

She/it talks quite well of Haskell, indeed.

Haskell is a modern, […] language. […] There’s no type of6 system more powerful than Haskell.

But she hides what behind this:

Haskell provides workarounds to interact with the outside world.

Being a purely functional language by choice, it needs workarounds to interact with the outside world. It is not a feature nor a quality! It is a consequence of a choice. Other functional languages make things easier by being less strict, less pure.

C#

[…] C# shares most of its cons with Java.

Maybe she refers to the fact that it runs in a virtual machine?

C# focuses mostly on OOP.

This sentence doesn’t make sense. Java is an OOP language, too. You are forced to put everything in a class (not like C++), but this doesn’t mean programmers will write OO-ish code… And the same goes for C#. And any other OO programming language: there’s always a way to write highly procedural code even in the most OO-focused language; let’s think about Smalltalk.

C# enables developers to build many types of secure and robust applications.

Another nonsense — not even false! 😀 It seems more like advertising.

Python

Python […] is easy for beginners to learn because of its readability

If this is what makes a language easy for beginners, I daresay there are language which are at least as readable as Python. Every language looks less readable if programmers use bad style.

Compare Python forcing indentation — not a good thing at all, IMO — with autoformatting code in the language X before presenting it to a beginner…

Python is an interpreted language and is notorious for being one of the slowest programming languages

Notorious? Is it? It seems stale information! Anyhow…

It depends on the implementation. And “interpreted language” doesn’t mean too much; some implementation could JIT compile the code, for example. If it is slow, it is slow because its most used implementation is slow. Let’s wait for a faster “interpreter”, or a compiler.

But first, we need to ask ourselves: do I need speed? Where do I need speed? A common path when you need to squeeze every possible particle of time, is to write the CPU-intensive code in a language which can be compiled to native code, and to call that code from inside Python. This is true for other languages as well: write native code for the CPU-intensive algorithms.

With Python you have packages like numpy, scipy, pandas, TensorFlow… Not exactly the kind of things you’d do with a language which is notoriously among the slowest programming language. Surely you could have better performance with an all-native-code (let’s say, C++) well-crafted software; but you would be trading something with something else…

Python has no proper support for functional programming.

I don’t know what qualifies as proper support in her head, but you can write functionally in Python. You can pass lambdas around (and they are closures, if I remember correctly), and we have map, filter, iteration over collection, and so on. Not so nice like in truely functional languages, maybe — but anyway… I’d say the support is proper. Compare Ruby

[1,2,3,4].map{|v| v*5}

and Python7:

map(lambda x: x*5, [1,2,3,4])

and Haskell:

map (*5) [1,2,3,4]

and Java with streams:

var x = Stream.of(1, 2, 3, 4).map((n) -> n * 5).toList();

Warning! the result is immutable! Functional languages work better with immutability… But Java isn’t that kind, and so you can have a mutable collection:

var x = Stream.of(1, 2, 3, 4).map((n) -> n * 5)
              .collect(Collectors.toList());

If we have lambdas, we can pass them around as we do with variables — and this is an important feature for functional languages. We can do also this:

def a(x):
  return x*5

def b(f, i):
  return f(i) + 1

c = lambda x: b(a, x)
map(c, [1,2,3,4])
# or inlining c:
map(lambda x: b(a, x), [1,2,3,4])
# or using again a def would work too!

In Haskell we have currying, so it may look a little bit tidier:

a x = x * 5
b f i = f i + 1
map (b a) [1, 2, 3, 4]

We see currying at work: b takes two arguments; so b a is a function that can be applied to a single argument (the one the map will feed in)8. Indeed, we’ve seen it already in map (*5) [1,2,3,4]: in fact * is a binary operator, and we “bind” one of its argument to a value, obtaining a single argument function.

Back to the matter of Python not having proper functional support: ok, it is not Haskell, or another among more functional languages; but it has enough — isn’t proper according to which criteria? And it is unclear why this lack of proper functional support would be an issue in Python and not in other languages — and why would this “issue” make a langauge not up to the mark?. Has Java proper support for functional programming? What about C#? And Ruby?

Scala

It is arguably one of the oldest modern programming languages.

When I say modern, I mean updated recently, in my era. So that maybe it keeps pace with innovations coming from current language research, or contemporary computing challenges, or just hype.

I don’t know what she means by Scala being the oldest among the modern languages. Is it even a feature?

Scala […] lacks proper type inference.

This is false: Scala has type inference, and it has had type inference since its first release in 20049.

The AI compiling this crap of an article was wrong — do not trust AIs: they are cool software running on computers, and can fail even more spectacularly than humans.10

TypeScript

[…] TypeScript […] uses type inference to give you great tooling without additional code

Indeed type inference isn’t a hot new thing. Even C++ has it (since C++11). We have seen that Scala has it since 2004, so that sentence could have been:

Scala uses type inference to give you great tooling without additional code

You can replace Scala with any other language having type inference. And languages that do not have it, do they have less than great tooling unless you write additional code?

The additional code being the type of an expression… Ok, in C++ with templates it can be hard… you needed a little bit of thinking, … or tools to help you (including error messages from the compiler). Now, you just write auto… Less typing for sure! Does less typing imply great tooling?

Go

She doesn’t speak bad of Go, but then: what about the title of the article?

Go was designed to help with programming productivity in the era of multicore processors and large codebases.

Programming languages are always designed to help someway. About large codebases, I think something like Ada is a lot better than what Go has.

I would say, indeed, that Go has a rather primitive and basic approach: not so many feature to help with large codebases. Just the bare minimum. Of course you can have large codebases in any language — even C… just saying.

Go makes the developer handle possible errors explicitly.

I think she refers to the lack of exceptions. Even when exceptions exist, your error handling is still somewhat explicit — but I understand what she’s saying.

There are reasonable explanation on why they preferred to avoid exceptions.

Go intentionally omitted many OOP features, as to not repeat the mistakes of C++.

It is just another approach.11 OOP (as we got used to think of it) is overrated, anyway; and often misused.

Rust

Rust is a modern low-level language, […]

Define low-level! It isn’t more “low-level” than C++, but she didn’t mention that C++ is low-level when she wrote about C++.

Compilation of Rust programs takes longer than a compilation of Go programs.

I don’t know if it is true — but anyway: so what? And why does she compare compilation time of Rust and Go, and not of Rust and Java, or Rust and X…? Nonsense. Just a piece of informantion thrown there without a real purpose but filling the paragraph.

Rust provides a modern alternative to nulls and a modern way of handling errors.

Without exception.

From Error Handling on the Rust site:

Rust doesn’t have exceptions. Instead, it has the type Result<T, E> for recoverable errors and the panic! macro that stops execution when the program encounters an unrecoverable error.

This turns out to be not that different from Haskell, which has Maybe which can be Just aValue or Nothing. And sooner or later you have to handle that: at a certain point you’ll match Just aValue to take a aValue, or Nothing to handle the error. You can let the variable of type Maybe propagate until the last point, when you actually need it. On the other hand, Go handles them like this:

func Sqrt(f float64) (float64, error) {
    if f < 0 {
        return 0, errors.New("math: square root of negative number")
    }
    // implementation
    return computedSqrt, nil
}

// ...
if result, err := Sqrt(-1); err != nil {
  fmt.Println(err)
} else {
  fmt.Println(result)
}

As you can see, result holds the correct value iff the operation succeeded. You can’t let result propagate back in the chain of clients, because they can’t say if the value is correct or fake. You can propagate the pair result, err, though, up to the point where a client (caller, if you prefer) needs to actually use the result.

Conclusion

The incipit of the article states (emphasis added):

Learning a new programming language is a big investment in time, energy, and brainpower. […] In this article, I’ll attempt to give a list of the top 10 modern programming languages that are not up to the mark.

The languages are:

  • C++
  • Java
  • Haskell
  • C#
  • Python
  • Scala
  • TypeScript
  • Go
  • Rust
  • Javascript

I think that all these languages are worth learning for a reason or another — with the only exception of Java, which I’d remove from the list of usable language… just joking! If your learning time is limited, likely you’ll be forced to pick just fews of them; but it’s a pity: I think that the more languages you experiment with, the better programmer you can become. And you add tools to your belt, which isn’t a bad thing.

Learning a language doesn’t mean you must become an expert of that language, and be able to use it idiomatically as the best programmers of that language. It means getting acquainted, taste them just enough to have an idea of their powers and abilities — then, what you will be using everyday likely depends on your employers and work environment, rather than your will. As sad as it may seem, it is a fact — unless…

Instead, according to this article, those languages are not up to the mark, although being modern. Let me add some notes:

  • C++: this is definitely a language you should know (altogether with C, which is a different language). Mastering it at 100% is very hard, but you need to know its powers, and to try at least once to exploit some of them in a toy project. Will you use it everyday then? It depends on the industry you’re working for.
  • Java: unfortunately this is widely used in the most overcrowded, low-skills-demanding industry, as well as in high-skills-demanding ones. Once a language becomes so popular, it gets enriched with good tools and libraries and frameworks and so on. These make life easier, and so the language attracts even more users, despite being not the best tool for everything. But if you want a job, likely it is better you don’t cut yourself out by refuting to use this language.12
  • Haskell: pure functional languages are a challenge if you’re too much accustomed to procedural or OO programming; this alone is a reason to give them a try: to open up your mind to other worldviews. Less common languages might be popular in specific industries: that is, if you’ll be using it for real or not likely will depend on your matter. I’ve heard that functional languages do well in financial applications.13
  • C#: the same speech of Java… I think that Java and C# are two languages competing for the same niche; what you’ll be using depends on the history of your employer. If it orbits around Oracle planet, or around Microsoft planet — mixtures are possible, I suppose, but I am not sure they exist.14
  • Python: you should learn it because it is a good tools for a lot of things; the more it gets used, the more tools it will have, the more people will use it because it allows you to develop something swiftly. It doesn’t mean that it is easy — programming isn’t easy, but building stuffs by composing already made “components” is certainly faster and easier than programming everything from scratch15. Interpreted languages like Python can be very useful for scripting.
  • Scala: I don’t like it very much, but I can say something similar to Haskell.
  • TypeScript: if you are into the world of Javascript, client side and/or server side (e.g., with node.js), you could consider to learn TypeScript, which is a sort of superset of Javascript. Javascript isn’t strongly typed, and this is a good thing for certain kind of development16, but in other cases can be better to have checks on types — plus more.
  • Go: surely worth learning especially for “backends” (server side code) and networking stuffs.17
  • Rust: advertised as strong in safety, and likely it is — with stress over memory management. But it is also low-level, in the same sense C++ is — but this does not mean much, anyway — also because it has packages which can help you18 a lot in many common complex tasks.19
  • Javascript: if you are into developing web application, you should know this as part of the web related technologies stack. You can use it also for scripting; the node.js echosystem is rich of tools.20

Clearly I wouldn’t stop at those languages: there are so many more, and it is always interesting to taste them and check what they can do for you. Of course, it’s hard you will ever use all of them in your job. But the more tool you have in your belt, the better.21


  1. The JVM can JIT-compile exploiting the “right” CPU instructions; if you’ve compiled your C++ program for a generic CPU, unlikely you’ll use certain powerful instructions which can boost you speed a lot; and your program could seem to run slower than Java. An Italian article about this; Briefly: add the proper options when compiling: -O3 but also things like -msse2 and -mfpmath=sse (depending on your CPU and compiler).↩︎

  2. If you implement a bubble sort in C and a QuickSort in Java… you are cheating, of course.↩︎

  3. Modern C++ is growing in that area too; C++17 has parallel algorithms in the STL. Before certain features were added directly to the language, it was anyway always possible to use things like pthread (or other libraries supporting concurrency on a specific OS) to do concurrency. Was that rudimentary? For sure we invent and enhance computer languages to abstract things, hence making less and less rudimentary to do things. But where do you set the bar to make a judgement? Back in the days when a language was born, or nowadays, taking into account the latest standard, the latest libraries, and so on?↩︎

  4. Fortran is a very old language, surely born in the era of single-core computing, but modern Fortran has its own ways towards concurrency — different from the mentioned languages. I am not talking about the use of OpenMP, which isn’t exactly recent, but of coarrays.↩︎

  5. Akka is written in Scala, which is another language targetting the very same Java Virtual Machine.↩︎

  6. Type of system or type system? I’d say the latter.↩︎

  7. In order to obtain the same output, you’ll need to wrap the expression in list(·).↩︎

  8. It was fortunate I put i as second argument, isn’t it? But if I didn’t, I could’ve used flip: map (flip b a) [1,2,3,4] — which works if b is defined as b i f = f i + 1. But if your code gets filled by flip, likely it is better you flip the arguments in the definition of b, as I did.↩︎

  9. Idid a little search using the Bard.↩︎

  10. AIs are made by humans. So there’s a double layer of possible mistakes. AIs aren’t intelligent at all, and neither are smart all the things we call smart. But maybe one thing is true: once humans give up their abilities and stop using their brains and start behaving more like computers executing tasks according to algorithms, it becomes easier to replace them with a mechanism.↩︎

  11. You can define struct types and interfaces. A variable of a type can have methods (sort of) attached to it, and “properties” of a struct can be public or private, and can be composed. This is enough to have a specific useful subset of what you are used to have in OO languages of the kind we learned to think about as what OO languages should be. One should first ask him/herself about the benefit of OOP.↩︎

  12. I am a huge hater of the language; but I am using it, and sometimes I’m even enjoying doing so — also because I find other reasons to dislike it altogether with the culture surrounding it…↩︎

  13. Surely you need to pair the knowledge of the language with the knowledge of fine math, though. I suspect you get paid high not just because you can use Haskell, but because you can also turn complex financial models into Haskell.↩︎

  14. Speaking about languages and language features, I think C# is better than Java. But this is another story.↩︎

  15. Making actual things is a good mind exercise. But most of the time they don’t need a smart guy: they need an obedient monkey who can assemble parts into a working whole in a short amount of time. The vast majority of programming isn’t cut-edge; and it is also the part which could be automated: assembling components and applying some business logic on top (provided proper specifications) can be done by an AI. That’s why one can be concerned by the current development in that matter. Therefore, a little advice: do not be a monkey: always try to add some extra value, something that can’t be deduced from the already given details. Try to make the step longer than your leg — literal translation of a saying… I don’t know if it works in English too — and to leave your footstep on sands hardly reacheable by mechanisms.↩︎

  16. At the beginning javascript was used just in web pages (running on the client) to do fency stuffs. Now we have complex web applications, and Javascript is used also in the backend. It isn’t just few lines of code here and there anymore… A strongly typed language (plus some more often desiderable features) is a good idea. I would give haxe a try, but it is not even mentioned here.↩︎

  17. It has good tools. I have doubts on the go.mod approach, and packages management in general. But it is a terse, clean language, with no frills and few traps, it gets compiled to native code, statically (no dependencies! no risks to break things changing a library!), and even cross-compiling is easy, for easy deployment under different operating systems. Good packages for networking, formatting, encoding/decoding…↩︎

  18. Do you need safe crypto libraries? Do you need web or network programming? And it isn’t “hard” as it is to use C++ libraries…↩︎

  19. Just another stab at Java: replacing it can have advantages. Tilde, an early production user of Rust in their Skylight product, found they were able to reduce their memory usage from 5GiB to 50MiB by rewriting certain Java HTTP endpoints in idiomatic Rust. When it comes to memory and resources consumption, it isn’t hard to believe that Java sucks there, too. If you live in a rotten work environment where this is good because it lets other departments to earn money (upgrading hardware has a cost, and people get paid to do it!)… then you won’t strive for sparing hundreds of Mbytes and who knows how many CPU cycles…↩︎

  20. Examples: do you have OpenAPI specs somewhere? Do you need a mock? Packages like this can do the trick. But there’s a lot more: do you need a web framework? Do you need to minimize CSS? Are you thinking about a file manager for the web? Are you into development of web and native user interfaces? Do you need a promise based HTTP client? Do you need a redis client, or maybe some crypto functions? And so on.↩︎

  21. And when you have a wider view of all ideas in the computer programming languages, you start thinking that the language you are forced to use lacks this or that…↩︎

No comments:

Post a Comment