For performance, write it in C

On Thu, Jul 27, 2006 at 01:59:37PM +0900, Chad P. wrote:

In fairness, if you’re judging it’s performance based on running it in
Wine, that’s not really a fair comparison. :slight_smile:

I’m judging it based on running it on Windows. My point is that
divorcing it from the only environment in which it runs (natively) is
less than strictly sporting of you, when trying to discuss its
performance characteristics (or lack thereof).

Wait… I did no such thing. All I said was that what interface
sluggishness you get from Excel can’t be blamed on Excel. They’re
performance characteristics that can be divorced from Excel (because
they’re Window’s own performance characteristic, not Excel’s). Argue
those points, and you’re arguing about the wrong software.

But Wine is an emulator, and while it does a good job approaching the
speed of Windows, it doesn’t hit it, nor can it hit it. You’re not
comparing like with like. Now that’s far from sporting.

You’re argument it disingenuous. Consider Cygwin running on Windows
compared to FreeBSD running on the same machine. I can make this
comparison because the machine I’m currently using dual-boots such a
setup. I run many of the same applications under Cygwin as I do under
FreeBSD on the same box. Those same applications running under Cygwin
are noticably slower than the native equivalents under FreeBSD. Do I
blame the software I’m running under Cygwin for being slow? No, because
I’m well aware that it zips along in its native environment. Do a blame
Cygwin? No, because it does an awful lot of work to trick the software
running under it that it’s running on a *nix. Do I blame Windows? No,
because I use some of that software–gcc being an example–natively
under Windows and it performs just as well as when it’s ran natively
under FreeBSD. Bringing Wine in is a red herring. Software cannot be
blamed for the environment it’s executed in.

K.

On Thu, Jul 27, 2006 at 02:26:37PM +0900, Keith G. wrote:

they’re Window’s own performance characteristic, not Excel’s). Argue
those points, and you’re arguing about the wrong software.

Design decisions that involve interfacing with interface software that
sucks is related to the software under discussion – and not all of the
interface is entirely delegated to Windows, either. No software can be
evaluated for its performance characteristics separate from its
environment except insofar as it runs without that environment.

But Wine is an emulator, and while it does a good job approaching the
speed of Windows, it doesn’t hit it, nor can it hit it. You’re not
comparing like with like. Now that’s far from sporting.

Actually, no, it’s not an emulator. It’s a set of libraries (or a
single library – I’m a little sketchy on the details) that provides the
same API as Windows software finds in a Windows environment. An
emulator actually creates a faux/copy version of the environment it’s
emulating. It is to Linux compared with Unix as an actual emulator is
to Cygwin compared with Unix: one is a differing implementation and the
other is an emulator.

. . . and, in fact, there are things that run faster via Wine on Linux
than natively on Windows.

[ snip ]

under FreeBSD. Bringing Wine in is a red herring. Software cannot be
blamed for the environment it’s executed in.

I didn’t bring it up. You did. I made a comment about Excel not
working in Linux as a bit of a joke, attempting to make the point that
saying Excel performance can be evaluated separately from its dependence
on Windows doesn’t strike me as useful.

Kroeger, Simon (ext) wrote:

real 473m45.370s

$size = (ARGV.shift || 5).to_i
$latins = []
$latins.each do |latin|
$perms.each do |perm|
perm.each{|p| puts $out[latin[p]]}
puts
end
end

(does someone has a nicer/even faster version?)

Here’s a much slower version that has no ‘require’.

Wd = ARGV.pop.to_i
$board = []

Generate all possible valid rows.

Rows = (0…Wd**Wd).map{|n| n.to_s(Wd).rjust(Wd,‘0’)}.
reject{|s| s=~/(.).*\1/}.map{|s| s.split(//).map{|n| n.to_i + 1} }

def check( ary, n )
ary[0,n+1].transpose.all?{|x| x.size == x.uniq.size }
end

def add_a_row( row_num )
if Wd == row_num
puts $board.map{|row| row.join}.join(’:’)
else
Rows.size.times { |i|
$board[row_num] = Rows[i]
if check( $board, row_num )
add_a_row( row_num + 1 )
end
}
end
end

add_a_row 0

On my machine it took around 33 seconds but I think that I can improve
it a little, besides I have to test the results first.

On Wednesday 26 July 2006 23:13, Chad P. wrote:

I recently rewrote an 830 line Java/
Hibernate web service client as 67 lines of Ruby, in about an hour.
With that kind of productivity, performance can go to hell!

With a 92% cut in code weight, I can certainly sympathize with that
sentiment. Wow.

Even the last remaining member of the Anti-Ruby Defence League in my
office
admitted (reluctantly) that it was impressive!

Ashley

On Thursday 27 July 2006 05:23, Francis C. wrote:

especially arrays- declare them outside your inner loop and re-use them
with Array#clear.

Nice MD5 trick! I’ll remember that. Fortunately the files that need
duplicate elimination are really small, so I won’t need to resort to
that.
But I’ll remember it for future reference.

Obviously I haven’t seen your code or your data, but if the Ruby app is
memory-bus-bound, then this approach may make your problem worse, not
better.

Hadn’t thought of that, good point…

Good luck. I recently got a Ruby program that aggregates several LDAP
directory-pulls with about a million entries down from a few hours to a
few seconds, without having to drop into C. It can be done, and it’s
kindof fun too.

Next time I get a morning free I might apply some of the tweaks that
have been
suggested. Might be interested to see how much I can improve the
performance.

Cheers
Ashley

Hal F. wrote:

I won a bet once from a friend. We wrote comparable programs in
Java and C++ (some arbitrary math in a loop running a bazillion
times).

With defaults on both compiles, the Java was actually faster
than the C++. Even I didn’t expect that. But as I said, this
sort of thing is highly dependent on many different factors.

Hal

Sometimes when we look at different workloads we can see the
performance crossover when relatively slow startup is overcome, code
JIT’d and adaptive optimisation kicks in

http://shootout.alioth.debian.org/gp4/fulldata.php?test=nbody&p1=java-0&p2=gcc-0&p3=clean-0&p4=java-0

Sorry for coming late to the party.

On Jul 26, 2006, at 1:47 AM, Peter H. wrote:

Whenever the question of performance comes up with scripting
languages such as Ruby, Perl or Python there will be people whose
response can be summarised as “Write it in C”.

The conclusion is wrong in the general case. Suppose that, instead
of computing permutations, your task had been to read ten million
lines of textual log files and track statistics about certain kinds
of events coded in there. I bet a version coded in perl, making
straightforward uses of regexes and hashes, would have performance
that would be very hard to match in C or any other language. Ruby
would be a little slower I bet just because Perl’s regex engine is so
highly-tuned, although it’s been claimed Oniguruma is faster.

So, first gripe: C is faster than Ruby in certain problem domains.
In others, it’s not.

Second gripe. The notion of doing a wholesale rewrite in C is almost
certainly wrong. In fact, the notion of doing any kind of serious
hacking, without doing some measuring first, is almost always wrong.
The right way to build software that performs well is to write a
natural, idiomatic implementation, trying to avoid stupid design
errors but not worrying too much about performance. If it’s fast
enough, you’re done. If it’s not fast enough, don’t write another
line of code till you’ve used used a profiler and understand what the
problem is. If in fact this is the kind of a problem where C is
going to do better, chances are you only have to replace 10% of your
code to get 90% of the available speedup.

And don’t remember to budget downstream maintenance time for the
memory-allocation errors and libc dependencies and so on that cause C
programs to be subject to periodic downstream crashes.

-Tim

[email protected] writes:

Are there
good benchmarks for OO languages? Or dynamic languages? Are there good
benchmarks that could actually measure the types of uses I need, where I’m
building a web front end to a DB store? I don’t know about you, but my job
has never involved fractals.

There was posted here a few weeks ago, in a thread on rails
performance, a benchmark that measured how fast a “hello world” web
app could respond under heavy load. This doesn’t measure the DB back
end piece, of course, but it’s a little closer to useful for you than
Mandelbrot calculations.

In fact, digging through Google desktop searches of my recently
visited web pages finds it here:

http://www.usenetbinaries.com/doc/Web_Platform_Benchmarks.html

Rails loses this contest big-time. Perl CGI scripts even beat a Rails
FastCGI setup. Rails FastCGI is about 15 times slower than plain ruby
FastCGI.

Also, it seems clear that at least for very simple web apps, PHP 4 to
PHP 5 is a distinct performance regression.

Chad P. wrote:

The canonical example for comparison, I suppose, is the Java VM vs. the
Perl JIT compiler. In Java, the source is compiled to bytecode and
stored. In Perl, the source remains in source form, and is stored as
ASCII (or whatever). When execution happens with Java, the VM actually
interprets the bytecode. Java bytecode is compiled for a virtual
computer system (the “virtual machine”), which then runs the code as
though it were native binary compiled for this virtual machine. That
virtual machine is, from the perspective of the OS, an interpreter,
however. Thus, Java is generally half-compiled and half-interpreted,
which speeds up the interpretation process.

Huh? Small-system (PDA, etc.) Java implementations may use bytecode
interpreters, but the mainstream ones started out using JIT, and were
later upgraded to start execution by interpreting, and then, if and when
it observes that a given segment is being repeatedly executed, compile
it to native code.

David P. wrote:

There are some applications that will never perform as in Java (e.g.,
stuff that’s heavily oriented to bit manipulation.) But for many
classes of applications (e.g., spreadsheets) Java can perform as well
as C.

Actually, it’s notorious that a Sieve of Eratosthenes using the
respective Bitset classes is faster in Java than in C++.

I don’t get it, either, but I’ve verified it myself.

On Fri, Jul 28, 2006 at 11:05:11AM +0900, John W. Kennedy wrote:

which speeds up the interpretation process.

Huh? Small-system (PDA, etc.) Java implementations may use bytecode
interpreters, but the mainstream ones started out using JIT, and were
later upgraded to start execution by interpreting, and then, if and when
it observes that a given segment is being repeatedly executed, compile
it to native code.

Wait . . . what? When some Java applet (for example) is sent over an
HTTP connection to your computer to be executed cient-side, it is NOT
just source code. Similarly, when you install a Java application, it
too is NOT simply copied onto the system in source code form. It’s
compiled to bytecode (or whatever the hell you want to call it) and
distributed thusly, for the JVM to run it.

Chad P. wrote:

Ada, on the other hand – for circumstances in which it is most commonly
employed (embedded systems, et cetera), it does indeed tend to kick C’s
behind a bit. That may have more to do with compiler optimization than
language spec, though.

Language specs mean a good deal, actually. C semantics (except in C99,
/if/ the restrict keyword is consistently used by the coder and
seriously implemented by the optimizer) lead to unnecessarily slow
object code in many common cases. Ada’s in-language support of tasking
also makes it easier for the compiler to know whether a segment of code
will or will not be multithreaded, which allows the compiler to optimize
more aggressively in many instances.

These are two of the reasons that so many C compilers include an
“optimize beyond safe limits” switch.

Indeed, many aspects of C’s design cause optimization problems.
0-terminated strings were dandy on 8-bit processors, but the S/370
actually had to add some new opcodes just to make strcpy and strcmp
tolerably fast.

Ada has another advantage in that the language design strongly
encourages designing global optimization into the compiler, whereas the
C tradition of make files tends to discourage it.

On 7/28/06, Chad P. [email protected] wrote:

Wait . . . what? When some Java applet (for example) is sent over an
HTTP connection to your computer to be executed cient-side, it is NOT
just source code. Similarly, when you install a Java application, it
too is NOT simply copied onto the system in source code form. It’s
compiled to bytecode (or whatever the hell you want to call it) and
distributed thusly, for the JVM to run it.

Interpretation does not necessarily mean raw source code is being
processed.
Even interpreters parse raw source into a form they can understand.
Interpretation in the Java VM comes in the form of bytecode
interpretation,
so called because instead of the system CPU running native operations
it’s
running another process that steps through the bytecodes. This is what’s
typically called “interpreted mode” in the JVM. However every VM since
Java
1.3 has taken the next step at run time and compiled that bytecode into
native processor instructions, so that the interpreter is no longer
involved
for those compiled pieces.

Bytecode is what’s distributed, yes, but it’s little more than
pre-parsed
and lightly optimized source code. You can convert it back to source, if
you
like. Your definition of “interpreted” is too narrow.

On Fri, Jul 28, 2006 at 11:30:05AM +0900, John W. Kennedy wrote:

Language specs mean a good deal, actually.

I didn’t say they didn’t. I said only that in this case it may be
that it’s more a matter of compiler optimization than language spec. I
don’t know enough about Ada to be able to comment authoritatively on the
comparison, but I certainly do know that language design can have an
effect (via the requirements it imposes on the implementation).

On Fri, Jul 28, 2006 at 02:32:20PM +0900, Charles O Nutter wrote:

Interpretation does not necessarily mean raw source code is being processed.
and lightly optimized source code. You can convert it back to source, if you
like. Your definition of “interpreted” is too narrow.

How do you figure? You just reiterated, in different words, everything
I said, then held it up as “proof” I’m “wrong”. I think you’re
violently agreeing with me, or something, and don’t realize it.

On Fri, Jul 28, 2006 at 02:34:21PM +0900, Chad P. wrote:

distributed thusly, for the JVM to run it.

Bytecode is what’s distributed, yes, but it’s little more than pre-parsed
and lightly optimized source code. You can convert it back to source, if you
like. Your definition of “interpreted” is too narrow.

How do you figure? You just reiterated, in different words, everything
I said, then held it up as “proof” I’m “wrong”. I think you’re
violently agreeing with me, or something, and don’t realize it.

No, just that you left out the bit about JIT compilation into native
code.

K.

On Jul 26, 2006, at 2:23 AM, Pit C. wrote:

Peter H. schrieb:

(Example of Perl and C Code)

Peter, is there any chance you could test your program with Ruby
Inline?

http://rubyforge.org/projects/rubyinline

I’m on Windows, so I can’t use Ruby Inline (+1 for MinGW btw :slight_smile:

Others have reported being able to use inline on windows… why can’t
you?

On Fri, Jul 28, 2006 at 02:53:09PM +0900, Keith G. wrote:

On Fri, Jul 28, 2006 at 02:34:21PM +0900, Chad P. wrote:

How do you figure? You just reiterated, in different words, everything
I said, then held it up as “proof” I’m “wrong”. I think you’re
violently agreeing with me, or something, and don’t realize it.

No, just that you left out the bit about JIT compilation into native
code.

Gee willickers, I’m sorry I didn’t use the exact phrasing you wanted me
to. Maybe next time, though, you won’t claim the bits I said that
didn’t actually have anything to do with your actual complaint were
wrong.

Y’know, screw it. Be an ass if you like. I’m done with this subthread.

Ryan D. schrieb:

On Jul 26, 2006, at 2:23 AM, Pit C. wrote:

I’m on Windows, so I can’t use Ruby Inline (+1 for MinGW btw :slight_smile:

Others have reported being able to use inline on windows… why can’t you?

Ryan, googling for

“ruby inline” windows

gave me no usable hint among the first 50 results besides using cygwin.
Do you have a link to the reports you mention?

Maybe I should have written that giving that I’m using the One Click
Installer, don’t have the Windows compiler toolchain, and am not willing
to use cygwin, I can’t use Ruby Inline. Is this better?

But, instead I might try to use Ruby Inline with MinGW, so thanks for
the question.

Regards,
Pit