Cracking DES with C++ is faster than Java?

Discussion in 'C++' started by Julie, Apr 25, 2004.

  1. 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.
     
    A. Lloyd Flanagan, May 5, 2004
    1. Advertisements

  2. And I gave examples of that.
     
    Douglas A. Gwyn, May 5, 2004
    1. Advertisements

  3. Julie

    newstome Guest

    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.)
     
    newstome, May 6, 2004
  4. 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
     
    Claudio Puviani, May 6, 2004
  5. Julie

    newstome Guest

    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).
     
    newstome, May 7, 2004
  6. 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
     
    Claudio Puviani, May 7, 2004
  7. 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.
    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.
     
    Douglas A. Gwyn, May 7, 2004
  8. I assume you meant *not* or *no longer* F-IV, as otherwise the "but"
    doesn't make sense plus it's quite wrong.
    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
     
    Dave Thompson, May 12, 2004
  9. Julie

    Jaap Guest

    Andrew Swallow schreef:
    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?
     
    Jaap, May 18, 2004
  10. Torsten Kirschner, May 18, 2004
  11. 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.
    People on this newsgroup tend to use C rather than Java.
    Both.

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

    Andrew Swallow
     
    Andrew Swallow, May 19, 2004
  12. It depends. Have a look at this link and decide for yourself.

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



    l8r, Mike N. Christoff
     
    Michael N. Christoff, Jun 3, 2004
  13. Julie

    Jerry Coffin Guest

    [ ... ]
    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.
     
    Jerry Coffin, Jun 4, 2004
  14. 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.
     
    Branimir Maksimovic, Jun 4, 2004
  15. 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 :)
     
    Branimir Maksimovic, Jun 4, 2004
  16. So java is SOOOOO slow they have to fake the benchmarks... But we already
    knew java is snail like.
    JP
     
    Jan Panteltje, Jun 4, 2004
  17. That's entirely wrong.
     
    Douglas A. Gwyn, Jun 5, 2004
  18. That's entirely wrong.
     
    Douglas A. Gwyn, Jun 5, 2004
  19. Julie

    Paul Schmidt Guest

    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.
    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
     
    Paul Schmidt, Jun 5, 2004
  20. Julie

    Luther Baker Guest

    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
     
    Luther Baker, Jun 5, 2004
    1. 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 (here). After that, you can post your question and our members will help you out.