Centrelink is actually the union of about half a dozen systems inherited from previous government agencies. Some of the systems run on mainframes, some on Novell, who knows what else. All of these systems don't really talk to each other well, and integration problems have been a nightmare for quite some time.
It'll be interesting to see precisely what they're planning to migrate to Linux.
Precisely, which is my main point: Writing the Linux kernel in C++ is a waste of time because right now, it's already written. Given that nobody wants to waste their time on this, we will never know if Linux is better written in C or C++.
I can only speak from the point of view of maintainability and readability, but you make a good point that if Linus et al can't read C++, then even this isn't necessarily an advantage.
It is truly ugly to have multiple acceptable coding paradigms in a large project [...]
Actually, most large software projects are multi-paradigm. This is because most large software projects have a "soft layer" DSL/scripting component (e.g. Emacs lisp). An OS kernel is a bit special in this regard, in that most of it is low-level stuff held together with internal APIs. The "soft layer" of Linux is user space.
Of course, if anyone feels like Linus is a total idiot, then they can try porting Linux to C++. I'm willing to bet that if someone could show substantial real benefits from a C++ Linux, Linus would happily eat his words.
This, of course, the wrong end of the proverbial stick. The benefit of C++ is that it lets you do pretty much what the kernel does now, only in a way that's easier to understand and more maintainable.
To get any substantial benefit for existing code, you'd need to translate the entire kernel into idiomatic C++, which is a huge task. For new code, OTOH, C++ compatability should be a win. Unfortunately, the only way to prove this is to a) support C++, b) implement the new code twice, once in C++ and once in C, and c) compare them.
Given that almost nobody is willing to implement their new feature twice just to prove a point...
My favourites are the Lagrangian (and Hamiltonian, for that matter) formulation of Newtonian dynamics. The Lagrangian one is: d/dt(dL/dq') + dL/dt = Q (where all derivatives are partial)
Not only does this sum up all of Newtonian mechanics, it also has the Newtonian part of Noether's theorem as a trivial corollary.
Noether's theorem, for the uninitiated, is a very deep law of nature. It states, more or less, that for every symmetry in a physical system, there is a corresponding conserved quantity. Examples:
If it doesn't matter where you perform an experiment, then momentum is conserved.
If it doesn't matter when you perform an experiment, then energy is conserved.
If it doesn't matter what phase your waves start at, then electric charge is conserved.
Re:Optimization Rules!
on
Optimizing Perl
·
· Score: 2, Insightful
Performance matters. And just like security, it can't be an afterthought.
Performance always matters. A program which computes the monthly payrolls is useless if it takes three months to run. However...
Performance may not be an issue in your particular program. If it's good enough, it's good enough.
"Performance" may not mean what you think it means. For one application, throughput (i.e. the amount of work you can do right before overload) is the most important consideration. For others, scalability, latency, memory usage or cache utilisation might be more important. Moreover, "performance" may not mean what you thought it meant when you started design.
A few minutes with the back of an envelope before you start coding often beats hours spent with profilers afterwards.
Time spent optimising the wrong piece of code is time wasted.
If performance really, really matters, plan to write a copy to throw away.
(And this is the most important of all...) The best favour you can do to your code with respect to performance is to write clean, well-compartmentalised code with good internal APIs and lots of unit and system tests. When you find a performance problem (and you will), you should be able to swap out bad code and swap in good code and (almost) nothing else will break. The corollary of this is that with performance, you need to design it in, but not necessarily code it in.
The theory is that a phone emitting low-power EM signals can induce an electric current in a hose full of moving petrol. Merely putting it in a chamber of fumes doesn't test what really goes on at a petrol outlet.
I have a mechanic who swears that he's seen video of the phenomenon happening. I realise that this is not proof, but this theory has the advantage that it's far more plausible than anything else I've heard. Oh, also, I live in a jurisdiction which uses GSM phones, so if anyone is going to try to reproduce it, use GSM.
Audiences today just don't like to watch untextured, cell-based cartoons anymore.
It's also undeniably true that Disney's films post-Katzenberg were almost all completely crap. With the exception of Final Fantasy: The Spirits Within, almost all 3D computer animated movies have ranged from quite good to excellent, largely because they've been created by newer teams who have been allowed to do their thing unhindered, releasing movies when they're ready.
I think you might find that Disney's upcoming 3D computer animated features are also going to flop, and it's not because of the visual style.
One of the design criteria of C++ is that you don't pay for what you don't use. If you write in the subset of C++ which is also in C, you get C (modulo some corner cases, like not being able to use "class" as a keyword). Indeed, you can't really get a C compiler these days; they're almost all C++ compilers with an internal command-line switch, or multiple-frontend compilers like GCC.
clone() is really an elegant solution to the whole problem [...]
Just being anal... clone() doesn't quite solve the whole problem. To pick one example: with clone(), tasks still have parent/child relationships. Unix semantics are that only a parent can wait() on a child, but pthreads semantics state that any thread can pthread_join() another (in the same process). There are a number of other problems like this (and they really do cause problems in practice) which make clone() less than useful in some kinds of application.
But it's also far less error prone than threads sharing variables when one thread forgets to get its locks right.
This is arguably a programming language issue more than anything else.
C has a very limited abstraction/protection model, which encourages manual lock management, so it's much easier to forget to lock something correctly than in, say, C++ (to pick but one). C also has issues with unlocking resources on exceptional conditions, which makes it difficult to write robust code in a multi-threaded environment.
If you read "The Art of UNIX Programming", threads are considered the last resort if no other IPC mechanism is fast enough.
If you read that book, you will find that the author is heavily biassed against threads. You get the impression that he's never had to solve a difficult synchronisation/scalability problem in his life.
Not that there's anything wrong with that. Threads are inappropriate for a lot of tasks, and if your programming career isn't very varied (from a concurrency point of view!) you may never come across a problem for which threads are the best answer. On the other hand, there are some problems for which they're the only practical answer. Being able to see which is which before you start coding is part of being a good developer.
Threads get a bad rap for two main reasons:
Some novice developers use threads when they're not the best solution. (And sometimes non-novices do, too. If you come from a non-Unix background, for example, you may not be used to fork().)
Threads are most useful for solving hard problems, and critics mistakenly point to the necessary complexity in the solution and say it's due to threads.
The last point is the most unfair. The concurrency problems in writing a typical DMBS or a typical GUI web browser would be just as tricky to solve with fork() than with threads (possibly even trickier, which is, no doubt, why fork() isn't used for these jobs).
Just saying "threads are bad, m'kay" cheats you and your users out of a good solution to many problems which turn up in practice.
Guess what? Typical UNIX software doesn't use threading. Forking is much easier, was there first, and is usually not significantly less efficient.
It depends what you call "typical".
A web server generally doesn't need shared data. Apache 1.x only uses shared data for a small amount of statistics gathering/monitoring, which is a very small amount of work compared with the job of actually serving HTTP, so the minor overhead in managing the shared data doesn't hurt very muvh at all.
The same applies to other kinds of server where little or no synchronisation is needed (e.g. telnet server, ftp server, ssh server).
At the other end of the spectrum is a program which does need synchronisation, but each request/response is quick. An X server is a good example. In this case, a single-task tight event loop architecture is appropriate.
And in the middle, you have a lot of jobs which aren't so simple. A typical DBMS is a good example of this. You have multiple concurrent tasks, which may take an unbounded amount of time, and which may require a nontrivial amount of synchronisation. The jobs aren't effectively sequential, meaning that SMP scalability is possible, but they're not completely isolated either. This is the kind of task where multi-threading is almost always the right answer.
Multi-threading is also commonly found in interactive GUI applications, where there may be long background tasks in conjunction with low-latency requirements.
So while it's true to say that typical Unix software, in the sense of most software that comes packaged on the CD from your vendor, is not multi-threaded, that's because most of that software doesn't have difficult synchronisation or scalability problems to solve. On the other hand, a lot of the software that you might buy or obtain after that is indeed multi-threaded.
It seems to me as though this would slow down the initial process of exploring the problem, as Paul Graham claims. Proponents claim that it makes up for that by making larger systems more reliable.
But these contest entries don't ever become large systems, and the extra slowdown initially wouldn't have time to pay off in the long run if the long run is only 24hrs (or 72hrs).
Personally, I find that the extra slow down in exploring data models and so on is paid back in less time debugging. (What a Lisp programmer might call "satisfying the whims of the type system" I find is better called "removing bugs which don't have to be tracked down later".) Moreover, once you've gotten the types satisfied, you can optimise your code and, thanks to type correctness, be pretty confident that you haven't inadvertantly broken anything. In the real world, of course, you'd have unit/coverage tests to ensure this for you. In a fast competition-like situation, you usually don't have time to write adequate tests, so getting the compiler to debug your code for you is invaluable.
In the end, though, it depends on the programmer. Some programmers are careful, others are assertive. Dynamically-typed languages might appeal to careful programmers more than statically-typed languages, because it gives you a little extra freedom. Assertive programmers might prefer statically-typed languages because you maximise the amount of drudge work that you have to do, offloading more of it onto your compiler.
Tell that to Thomas Becket.
"Who will rid me of this turbulent priest?"
Whether or not it's a threat depends on who makes it, and that's what the SS was there to find out.
Centrelink is actually the union of about half a dozen systems inherited from previous government agencies. Some of the systems run on mainframes, some on Novell, who knows what else. All of these systems don't really talk to each other well, and integration problems have been a nightmare for quite some time.
It'll be interesting to see precisely what they're planning to migrate to Linux.
Precisely, which is my main point: Writing the Linux kernel in C++ is a waste of time because right now, it's already written. Given that nobody wants to waste their time on this, we will never know if Linux is better written in C or C++.
I can only speak from the point of view of maintainability and readability, but you make a good point that if Linus et al can't read C++, then even this isn't necessarily an advantage.
Actually, most large software projects are multi-paradigm. This is because most large software projects have a "soft layer" DSL/scripting component (e.g. Emacs lisp). An OS kernel is a bit special in this regard, in that most of it is low-level stuff held together with internal APIs. The "soft layer" of Linux is user space.
This, of course, the wrong end of the proverbial stick. The benefit of C++ is that it lets you do pretty much what the kernel does now, only in a way that's easier to understand and more maintainable.
To get any substantial benefit for existing code, you'd need to translate the entire kernel into idiomatic C++, which is a huge task. For new code, OTOH, C++ compatability should be a win. Unfortunately, the only way to prove this is to a) support C++, b) implement the new code twice, once in C++ and once in C, and c) compare them.
Given that almost nobody is willing to implement their new feature twice just to prove a point...
Wives tend to have high false positive rates, though.
My thoughts exactly. 640kb should be enough for everyone.
My favourites are the Lagrangian (and Hamiltonian, for that matter) formulation of Newtonian dynamics. The Lagrangian one is: d/dt(dL/dq') + dL/dt = Q (where all derivatives are partial)
Not only does this sum up all of Newtonian mechanics, it also has the Newtonian part of Noether's theorem as a trivial corollary.
Noether's theorem, for the uninitiated, is a very deep law of nature. It states, more or less, that for every symmetry in a physical system, there is a corresponding conserved quantity. Examples:
Performance always matters. A program which computes the monthly payrolls is useless if it takes three months to run. However...
I think you're referring to C++.
And remember, TeX is still written in Pascal.
The number of Internets on the Internet is... ah, ever mind.
(I wonder if will end up the easiest +5 Funny ever. We shall see.)
Errr... no.
The theory is that a phone emitting low-power EM signals can induce an electric current in a hose full of moving petrol. Merely putting it in a chamber of fumes doesn't test what really goes on at a petrol outlet.
I have a mechanic who swears that he's seen video of the phenomenon happening. I realise that this is not proof, but this theory has the advantage that it's far more plausible than anything else I've heard. Oh, also, I live in a jurisdiction which uses GSM phones, so if anyone is going to try to reproduce it, use GSM.
So a vote for Nader is a vote for Bush, then?
It's also undeniably true that Disney's films post-Katzenberg were almost all completely crap. With the exception of Final Fantasy: The Spirits Within, almost all 3D computer animated movies have ranged from quite good to excellent, largely because they've been created by newer teams who have been allowed to do their thing unhindered, releasing movies when they're ready.
I think you might find that Disney's upcoming 3D computer animated features are also going to flop, and it's not because of the visual style.
Why?
One of the design criteria of C++ is that you don't pay for what you don't use. If you write in the subset of C++ which is also in C, you get C (modulo some corner cases, like not being able to use "class" as a keyword). Indeed, you can't really get a C compiler these days; they're almost all C++ compilers with an internal command-line switch, or multiple-frontend compilers like GCC.
Just being anal... clone() doesn't quite solve the whole problem. To pick one example: with clone(), tasks still have parent/child relationships. Unix semantics are that only a parent can wait() on a child, but pthreads semantics state that any thread can pthread_join() another (in the same process). There are a number of other problems like this (and they really do cause problems in practice) which make clone() less than useful in some kinds of application.
This is arguably a programming language issue more than anything else.
C has a very limited abstraction/protection model, which encourages manual lock management, so it's much easier to forget to lock something correctly than in, say, C++ (to pick but one). C also has issues with unlocking resources on exceptional conditions, which makes it difficult to write robust code in a multi-threaded environment.If you read that book, you will find that the author is heavily biassed against threads. You get the impression that he's never had to solve a difficult synchronisation/scalability problem in his life.
Not that there's anything wrong with that. Threads are inappropriate for a lot of tasks, and if your programming career isn't very varied (from a concurrency point of view!) you may never come across a problem for which threads are the best answer. On the other hand, there are some problems for which they're the only practical answer. Being able to see which is which before you start coding is part of being a good developer.
Threads get a bad rap for two main reasons:
The last point is the most unfair. The concurrency problems in writing a typical DMBS or a typical GUI web browser would be just as tricky to solve with fork() than with threads (possibly even trickier, which is, no doubt, why fork() isn't used for these jobs).
Just saying "threads are bad, m'kay" cheats you and your users out of a good solution to many problems which turn up in practice.
It depends what you call "typical".
A web server generally doesn't need shared data. Apache 1.x only uses shared data for a small amount of statistics gathering/monitoring, which is a very small amount of work compared with the job of actually serving HTTP, so the minor overhead in managing the shared data doesn't hurt very muvh at all.
The same applies to other kinds of server where little or no synchronisation is needed (e.g. telnet server, ftp server, ssh server).
At the other end of the spectrum is a program which does need synchronisation, but each request/response is quick. An X server is a good example. In this case, a single-task tight event loop architecture is appropriate.
And in the middle, you have a lot of jobs which aren't so simple. A typical DBMS is a good example of this. You have multiple concurrent tasks, which may take an unbounded amount of time, and which may require a nontrivial amount of synchronisation. The jobs aren't effectively sequential, meaning that SMP scalability is possible, but they're not completely isolated either. This is the kind of task where multi-threading is almost always the right answer.
Multi-threading is also commonly found in interactive GUI applications, where there may be long background tasks in conjunction with low-latency requirements.
So while it's true to say that typical Unix software, in the sense of most software that comes packaged on the CD from your vendor, is not multi-threaded, that's because most of that software doesn't have difficult synchronisation or scalability problems to solve. On the other hand, a lot of the software that you might buy or obtain after that is indeed multi-threaded.
True. Rand's cult was a bit less bizarre.
Speaking as a fat bearded geek: If some chick was spying on me, there might be a good case to have her committed.
Also true of L. Ron Hubbard.
If you'd actually read the comments, even if you hadn't looked at the code, you'd have some idea just how "hardcore" this is.
Personally, I find that the extra slow down in exploring data models and so on is paid back in less time debugging. (What a Lisp programmer might call "satisfying the whims of the type system" I find is better called "removing bugs which don't have to be tracked down later".) Moreover, once you've gotten the types satisfied, you can optimise your code and, thanks to type correctness, be pretty confident that you haven't inadvertantly broken anything. In the real world, of course, you'd have unit/coverage tests to ensure this for you. In a fast competition-like situation, you usually don't have time to write adequate tests, so getting the compiler to debug your code for you is invaluable.
In the end, though, it depends on the programmer. Some programmers are careful, others are assertive. Dynamically-typed languages might appeal to careful programmers more than statically-typed languages, because it gives you a little extra freedom. Assertive programmers might prefer statically-typed languages because you maximise the amount of drudge work that you have to do, offloading more of it onto your compiler.