Cracking DES with C++ is faster than Java?


A

A. Lloyd Flanagan

There are a number of ways to write code which is valid C (i.e. C-89)
but illegal C++:
Perhaps, but the statement was that it wasn't "safe" to compile C code
with a C++ compiler. In almost every case you mentioned, the
construct in C is _disallowed_ by the C++ compiler. In the other
case, the compiler will allocate more memory than required, but that's
usually harmless. So it's still "safe" in the sense that if C++
compiles the code it should work correctly.

As for whether the resulting program is faster, slower, or
indistinguishable from the program produced by the C compiler, that's
entirely a function of the compiler. The C++ spec has a design goal
that no feature imposes a runtime penalty if it's never used in the
program; a decent compiler will skip all the overhead required for
C++-specific features if you don't use them.

I'd take a good C++ compiler over a mediocre C compiler in every case.
Of course, if your C++ compiler creates a 2 MB program to print
"hello, world", that's not a good compiler.
 
Ad

Advertisements

N

newstome

In sci.crypt Douglas A. Gwyn said:
And I gave examples of that.

I just looked back through this thread, and couldn't find any posting
from you giving such an example. I'm honestly curious: can you post
an example of something that is valid C and C++, but works differently
in the two languages? (I think that's what you're saying is possible.)
 
C

Claudio Puviani

I just looked back through this thread, and couldn't find any posting
from you giving such an example. I'm honestly curious: can you post
an example of something that is valid C and C++, but works differently
in the two languages? (I think that's what you're saying is possible.)

I know this wasn't addressed to me, but I'm sure you don't care who gives you the
examples.

First example: sizeof('x') == sizeof(int) in C but in C++ sizeof('x') ==
sizeof(char). Therefore, any code that uses the value of sizeof('x') will behave
differently under the two languages. This is because 'x' is of type int in C but
of type char in C++.

Here's another snippet, adapted from appendix C of the C++ Standard:

char a[100];
printf("%d\n", sizeof(0, a));

This will print 100 in C++ but it will print the value of sizeof(char *) in C.
The reason is that in C, the comma operator returns and r-value, but in C++, it
returns an l-value.

And another example adapted from that same appendix:

int x[99];
void f()
{
struct x { int a; };
printf("%d\n", sizeof(x));
}

This will print the size of the array in C, but in C++, it will print the size of
the struct. The reason for this difference is that C++ introduces the name of the
struct at the function scope thereby hiding the array. In C, the tag, 'x', has
no visibility past the declaration.

Granted, these are contrived examples, but the aim was to show differences, not
real-life code. I'm sure someone could find more examples.

Claudio Puviani
 
N

newstome

I know this wasn't addressed to me, but I'm sure you don't care who
gives you the examples.

Thank you! And now I learned several new things today!

I agree with you that those are contrived examples, and I'm not sure
if they'd ever really come up in practice (for example, I've been
programming in C for 20 years, and have never taken the sizeof a
constant). They're still really interesting points though, and show
at least the potential for problems when compiling C code with a C++
compiler...

Incidentally, I'd bet good money that the original version of C++ did
not have these issues, since Stroustrup's C++ "compiler" was really a
front-end pre-processor to a C compiler, and the core types remained the
same (in other words, I'd bet sizeof('a') got passed to the C compiler
exactly as sizeof('a'), so gave a 4).
 
C

Claudio Puviani

Incidentally, I'd bet good money that the original version of C++ did
not have these issues, since Stroustrup's C++ "compiler" was really a
front-end pre-processor to a C compiler, and the core types remained the
same (in other words, I'd bet sizeof('a') got passed to the C compiler
exactly as sizeof('a'), so gave a 4).

Interestingly, it's my understanding that this was there from the beginning, or
very close to it. The rationale behind this is that in C++, you can overload a
function for ints and chars:

void f(int v);
void f(char v);

and Stroustrup wanted an invocation of f('x') to call the appropriate overload,
i.e., the function taking char. Therefore, the type of a character literal was
changed from int to char.

Now, what the exact transformation was in cfront, you'd have to ask Bjarne. :)

Claudio Puviani
 
Ad

Advertisements

D

Douglas A. Gwyn

I agree with you that those are contrived examples, and I'm not sure
if they'd ever really come up in practice ...

There are other, less contrived examples of the difference
in the languages. The difference in type for character
constants can have a real impact. There are differences
in the "inline" capability that need to be understood in
order to code suitably for compiling under both languages.
One of the longest-standing practical differences is that
extern int foo();
has radically different meaning; there are legitimate uses
(other than support of legacy code) for such a construct
in C programming, e.g. command dispatch tables.
Incidentally, I'd bet good money that the original version of C++ did
not have these issues, since Stroustrup's C++ "compiler" was really a
front-end pre-processor to a C compiler, and the core types remained the
same (in other words, I'd bet sizeof('a') got passed to the C compiler
exactly as sizeof('a'), so gave a 4).

I don't recall whether "C with classes" and "Cfront" had
that particular difference, but they certainly did not
simply pass most constructs straight to C, so your line
of reasoning is invalid. Declarations were actually
parsed according to rules invented by Stroustrup, not
according to C. The generated C code was synthesized
anew, and generally did not much resemble the original
source code.
 
D

Dave Thompson

The reason Fortran (now FORTRAN IV though, but a mixture of

I assume you meant *not* or *no longer* F-IV, as otherwise the "but"
doesn't make sense plus it's quite wrong.
Fortran-77 and Fortran-90/95) is still used is that it's still the
most machine efficient language for heavy number crunching problems.
<snip> has evolved too, and Fortran-90/95 is a language very
different from FORTRAN IV - but it still focuses on generating
efficient code, and the language is designed such that aliasing
issues (which are so common in C and C++ and which makes optimization
of generated machine code much harder) does not exist in that
language.
Minor correction: do not exist *by default*. With F9X POINTERs and
TARGETs you *can* introduce nearly the same aliasing issues as in C --
and in C99 with restrict you can solve them, given compiler support.
But historically C compilers haven't provided much in this area and on
the whole C users haven't demanded it, while a significant fraction of
Fortran compilers and users have.


- David.Thompson1 at worldnet.att.net
 
J

Jaap

Andrew Swallow schreef:
[snip]
Around 1983-1985, the programming language Ada was envisioned to,
within 5-10 years, take over virtually all software development. At


Nightmare though. ADA is still being used in the latest military aircraft.

Andrew Swallow
what's wrong with ADA? I thought it was the first real oo-language? And
thut this make the aircraft in which it is being used less safe than an
aircraft with a VM running J2SE 1.4?
Is it the programmer or the language which makes the errors?
 
A

Andrew Swallow

Jaap said:
Andrew Swallow schreef:
[snip]
Around 1983-1985, the programming language Ada was envisioned to,
within 5-10 years, take over virtually all software development. At


Nightmare though. ADA is still being used in the latest military aircraft.

Andrew Swallow
what's wrong with ADA? I thought it was the first real oo-language? And

Object Orientation was added to Ada, it was about the one thing
that was not in the original standard. Data structures were.

The size and complexity of the language mean that it is slow
to compile. So iterative development can not be used. Neither
can write it, test it, find bug, correct bug, recompile, test and
find next bug. Or if the programmers are forced to use
debugging to get the thing to work your costs and timescales
go through the roof.

In ADA get you data structures right first or you are in big
trouble.
thut this make the aircraft in which it is being used less safe than an
aircraft with a VM running J2SE 1.4?

People on this newsgroup tend to use C rather than Java.
Is it the programmer or the language which makes the errors?

Both.

ADA does not think like a computer programmer, as a true
born daughter of the Pentagon she is a natural bureaucrat.

Andrew Swallow
 
Ad

Advertisements

J

Jerry Coffin

[ ... ]
It depends. Have a look at this link and decide for yourself.

http://www.idiom.com/~zilla/Computer/javaCbenchmark.html

Examine the code before drawing any conclusions. For example, here
are lines 215-222 of his life benchmark:

init0 = (int*)calloc(max_x,sizeof(int));
init1 = (int*)calloc(max_x,sizeof(int));
init2 = (int*)calloc(max_x,sizeof(int));
for (x=0; x<max_x; x++) {
init2[x] = 0;
init1[x] = 0;
init0[x] = 0;
}

calloc returns zero-initialized storage, but he immediately
zero-initializes the storage anyway. Either he was clueless, or he set
out with malice aforethought to show C as being slower than it really
is.

About the only conclusions that can reasonably be drawn from this
benchmark are about its author, NOT about the speed of C relative to
Java.
 
B

Branimir Maksimovic

Jerry Coffin said:
.........
About the only conclusions that can reasonably be drawn from this
benchmark are about its author, NOT about the speed of C relative to
Java.
I think that just reading following is enough :)
"
Most everyone says GC is or should be slower, with no given reason- it's
assumed but never discussed. Some computer language researchers say
otherwise.
Consider what happens when you do a new/malloc: a) the allocator wanders
through some lists looking for a slot of the right size, then returns you a
pointer. b) This pointer is pointing to some pretty random place.

With GC, a) the allocator doesn't need to look for memory, it knows where it
is, b) the memory it returns is adjacent to the last bit of memory you
requested. The wandering around part happens not all the time but only at
garbage collection. And then of course (and depending on the GC algorithm)
things get moved of course as well.

"
Greets, Bane.
 
B

Branimir Maksimovic

Branimir Maksimovic said:
............
I think that just reading following is enough :)
"
Most everyone says GC is or should be slower, with no given reason- it's
assumed but never discussed. Some computer language researchers say
otherwise.
Consider what happens when you do a new/malloc: a) the allocator wanders
through some lists looking for a slot of the right size, then returns you a
pointer. b) This pointer is pointing to some pretty random place.

With GC, a) the allocator doesn't need to look for memory, it knows where it
is, b) the memory it returns is adjacent to the last bit of memory you
requested. The wandering around part happens not all the time but only at
garbage collection. And then of course (and depending on the GC algorithm)
things get moved of course as well.

"
Even this simple implementation proves that assertion about
malloc/new is not general case.
#include <iostream>
#include <cassert>
using namespace std;
template <class T>
class Allocator{
public:
Allocator(unsigned how_many=1000);
void* malloc();
void free(void*);
~Allocator();
private:
Allocator(const Allocator&);
Allocator& operator=(const Allocator&);
void reserve(unsigned how_many);
union AllocatorNode{
AllocatorNode* next;
char object[sizeof(T)];
} *first_;
};

template <class T>
void Allocator<T>::reserve(unsigned how_many)
{
assert(how_many > 0);
AllocatorNode* init = 0;
AllocatorNode* tmp = (AllocatorNode*)&init;
while(how_many--)
{
tmp->next= (AllocatorNode*)::eek:perator new(sizeof(AllocatorNode));
tmp = tmp->next;
}
tmp->next = 0;
first_ = init;
}

template <class T>
Allocator<T>::Allocator(unsigned how_many)
: first_(0)
{
reserve(how_many);
}

template <class T>
Allocator<T>::~Allocator()
{
while(first_)
{
AllocatorNode* tmp = first_->next;
::eek:perator delete(first_);
first_ = tmp;
}
}

template <class T>
void* Allocator<T>::malloc()
{
if(!first_)reserve(1);
void* mem = first_;
first_ = first_->next;
return mem;
}

template <class T>
void Allocator<T>::free(void* p)
{
AllocatorNode* node = (AllocatorNode*)p;
node->next = first_;
first_ = node;
}


class Test{
public:
Test(int i):i_(i){}
int i(){ return i_; }
void* operator new(size_t s)
{
return mem_.malloc();
}
void operator delete(void* p)
{
mem_.free(p);
}
private:
int i_;
static Allocator<Test> mem_;
};

Allocator<Test> Test::mem_;

int main()
{
Test* t[100];
for(int i = 0; i<100; ++i)
{
t=new Test(i);
}
for(int i = 0; i<100; ++i)
{
cout<<t<<' '<<t->i()<<'\n';
delete t;
t = new Test(i);
cout<<t<<' '<<t->i()<<'\n';
}
for(int i = 0; i<100; ++i)
{
delete t;
}
}

Greets, Bane.

P.S. I can bet that no general GC can beat this one :)
 
J

Jan Panteltje

[ ... ]
It depends. Have a look at this link and decide for yourself.

http://www.idiom.com/~zilla/Computer/javaCbenchmark.html

Examine the code before drawing any conclusions. For example, here
are lines 215-222 of his life benchmark:

init0 = (int*)calloc(max_x,sizeof(int));
init1 = (int*)calloc(max_x,sizeof(int));
init2 = (int*)calloc(max_x,sizeof(int));
for (x=0; x<max_x; x++) {
init2[x] = 0;
init1[x] = 0;
init0[x] = 0;
}

calloc returns zero-initialized storage, but he immediately
zero-initializes the storage anyway. Either he was clueless, or he set
out with malice aforethought to show C as being slower than it really
is.

About the only conclusions that can reasonably be drawn from this
benchmark are about its author, NOT about the speed of C relative to
Java.
So java is SOOOOO slow they have to fake the benchmarks... But we already
knew java is snail like.
JP
 
Ad

Advertisements

D

Douglas A. Gwyn

Branimir said:
With GC, a) the allocator doesn't need to look for memory, it knows where it
is, b) the memory it returns is adjacent to the last bit of memory you
requested.

That's entirely wrong.
 
D

Douglas A. Gwyn

Branimir said:
With GC, a) the allocator doesn't need to look for memory, it knows where it
is, b) the memory it returns is adjacent to the last bit of memory you
requested.

That's entirely wrong.
 
P

Paul Schmidt

Branimir said:
........


I think that just reading following is enough :)
"
Most everyone says GC is or should be slower, with no given reason- it's
assumed but never discussed. Some computer language researchers say
otherwise.
Consider what happens when you do a new/malloc: a) the allocator wanders
through some lists looking for a slot of the right size, then returns you a
pointer. b) This pointer is pointing to some pretty random place.

Isn't this compiler/platform specific? I don't think modern compilers
wander through looking for specific memory sizes, it's easier to keep
two pointers, one is to a stack of deallocated space, the other to the
beginning of unallocated heap. The stack should be fairly short, and
can be traversed very quickly, then begining of heap, then allocates a
space the right size, if there is not enough space, it asks the OS for
another block. After 30 years, these routines are well tuned, and about
as fast as you can get.
With GC, a) the allocator doesn't need to look for memory, it knows where it
is, b) the memory it returns is adjacent to the last bit of memory you
requested. The wandering around part happens not all the time but only at
garbage collection. And then of course (and depending on the GC algorithm)
things get moved of course as well.

A garbage collector really has the same process at work, in the case of
Java, the GC determines when a portion of memory is deallocated. Some
GC's might also merge small adjacent blocks together, and shift
allocated blocks to try and minimize fragmentation. However this
introduces another problem, the application and GC then need to be
synchronized so that the GC isn't moving a block that the application is
using, and this introduces overhead for both. With modern computers
having huge memory resources, the overhead of packing memory isn't
really worth it.

Actually with C/C++ you can eliminate the new/malloc, simply allocate a
pointer called mem_head, malloc it some large amount of memory say 64MB.
Now allocate a second pointer called mem_cur set this equal to mem_head
, when you want memory do something like this:

int *my_ptr;
my_ptr = mem_cur;
mem_cur+=sizeof(int);

Now you have allocated the size of an int block of memory to my_ptr;
Yeah you will waste memory you would normally deallocate, but that is
the price you pay for speed.

At the end of the program simply call free or delete mem_head.

Try doing that with a Garbage Collector!!!!

Cracking DES, your probably best to write it in, uh, um assembler....

Paul
 
Ad

Advertisements

L

Luther Baker

Michael said:
It depends. Have a look at this link and decide for yourself.

http://www.idiom.com/~zilla/Computer/javaCbenchmark.html

These are circular arguments.

One can implement a JVM in C++.

Whatever advantage a particular JVM provides a Java implementation over
a C++ implementation, one can implement that advantage in C++.

Java functionality is essentially a subset of C++.

One might argue that implementation A (in Java) is faster than
implementation B (in C++), but that hardly has anything to do with
comparing performance of C++ vs. Java.

One might even argue that similar, simplistic implementations in Java
and C++ show the Java implementation to be faster. Such a report could
be titled "Java facilitates writing faster programs with simplistic
implementations ... or less understanding of how to take advantage of
the compiler, operating system or platform."

But again, that hardly compares C++ against Java.

My civic might get me started, out of my driveway and to the
neighborhood gas station minutes before my nitrous dragster. Its also
much faster to drive to the local mall instead of taking a plane. But
who would ever argue that my civic is faster than my dragster or my plane?

C++ can look like a civic, a dragster, a plane. At the very least, C++
can look like your JVM.

Furthermore, C++ is simply a language. Java is an execution context. The
real argument here is whether the machine code generated by a C++
program can be as fast as the code executing in a JVM. Such a stupid
assertion since, again, anything the JVM is doing can be implemented
into platform specific executable written in C++.

They are different languages with different idioms and different
execution contexts. Optimum implementations of anything in either
langauge might/can/should look radically different.

Reports like this do nothing but raise the noise floor.

-Luther
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top