Page 6 of 9 FirstFirst ... 45678 ... LastLast
Results 51 to 60 of 84

Thread: Mono 2.11 Release Brings Many Changes

  1. #51
    Join Date
    Nov 2009
    Location
    Madrid, Spain
    Posts
    304

    Default

    Quote Originally Posted by Ansla View Post
    Well, I did some micro-benchmarks with the corner-case suggested by ciplogic and this are the results:
    (...)
    Now, the obvious result is that Java is really slow! No excuses like long time spent unpacking archives or other bullshit, both the Icedtea and gcj implementations of Java are plain ridiculously slow. Mono actually does a decent job at this being faster then C++ with boost::shared_ptr, but still it doesn't justify switching to Mono if C++11 std::shared_pointer or boehm-gc are valid alternatives.( ...)
    Just as a reminder: C++ was the slowest, with no bullshit like "unpacking archives" or "I wanted to see just how much overhead copying the smart pointer could have" Wish to you a great time!

  2. #52
    Join Date
    Oct 2010
    Posts
    258

    Default

    LOL, when it's the only one being misused, yes

  3. #53
    Join Date
    Nov 2009
    Location
    Madrid, Spain
    Posts
    304

    Default

    Quote Originally Posted by Ansla View Post
    LOL, when it's the only one being misused, yes
    If you mean that C++ is misused by using smartpointers, I fully agree ( const & misses the point of using smartpointers in first place!), One platform (the VM) would have reference tracking for free, when other (native C++), will be an expensive feature, visibly slower than C#/Java.
    You can test other claims too, like:
    - new in C++ is much slower than new in C# (at least with generational collector, so add sgen to Mono's command line)/Java,
    - arrays in C#/Java (which are the closes equivalent with std::vector (as you cannot do pointer arithmetic, and you can also iterate over them) are in general faster than their C++ equivalent (on medium sized programs), because C#/Java have a bound's checking removal algorithms for these structures. You may also try if Java specializes OOP calls (using Polymorphic Inline Caching), making working with OOP a bliss
    - just upgrading Mono/JVM you can have faster programs with no change on your side (as Java VM or Mono's VM add optimizations, your applications will get them for free, but static compiled programs would not). You may try Jake2 game engine, and try the equivalent Quake2 demo, and tell me which is faster, as for my machine, Quake2/Java is faster than Quake2
    At the end, one very last cool thing Java/.Net world has, and C++ have harder times: to work with multiple (good) languages in parts of project and don't have "Invalid Read Address at 0x0ffaas5dda". I recommend to Kotlin (http://confluence.jetbrains.net/disp...etting+Started) which is Java based but brings some runtime warranties and is really nice to code in.

  4. #54
    Join Date
    Nov 2009
    Location
    Madrid, Spain
    Posts
    304

    Default

    Reddit-C++ page have a link one week ago, that states the same. And gave numbers how to improve 3x the reference counting, by removing the thread-save code.

  5. #55
    Join Date
    Oct 2010
    Posts
    258

    Default

    Quote Originally Posted by ciplogic View Post
    If you mean that C++ is misused by using smartpointers, I fully agree ( const & misses the point of using smartpointers in first place!), One platform (the VM) would have reference tracking for free, when other (native C++), will be an expensive feature, visibly slower than C#/Java.
    The misuse is not using smart pointers in the first place, but not passing them as const reference on the function call. Because if the function called is only using the pointer for the duration of its life time, not taking ownership by storing a copy of the pointer at some global level why increment the usage counter? Lets say your function actually does store it for later reference, then the code would look like this:
    Code:
    void ProcessItem(const std::shared_ptr<Item> &item) {
        someOtherSmartPointer = item;
    }
    This code will work as the assignment operator for shared_ptr (both the C++11 version and the boost version) take a const reference as parameter. So passing the smart pointer as value instead of reference is a misuse, especially because it can be passed around for many times before some function actually stores it for later use (or maybe it won't be stored at all).

    Quote Originally Posted by ciplogic View Post
    You can test other claims too, like:
    - new in C++ is much slower than new in C# (at least with generational collector, so add sgen to Mono's command line)/Java,
    That depends a lot on the malloc implementation wrapped around by C++ new. And also the average C#/Java program will do a lot more dynamic memory allocations then a C++ one because in C++ it's possible to place a temporary instance of a class on the stack, with C#/Java you can only store on the stack primitive types, any class has to be dynamically allocated.

    Quote Originally Posted by ciplogic View Post
    - arrays in C#/Java (which are the closes equivalent with std::vector (as you cannot do pointer arithmetic, and you can also iterate over them) are in general faster than their C++ equivalent (on medium sized programs), because C#/Java have a bound's checking removal algorithms for these structures. You may also try if Java specializes OOP calls (using Polymorphic Inline Caching), making working with OOP a bliss
    But an array in C#/Java can not be resized, and the main reason for using C++ std::vector is it's ability to resize at runtime, so they are not at all equivalent

    Quote Originally Posted by ciplogic View Post
    - just upgrading Mono/JVM you can have faster programs with no change on your side (as Java VM or Mono's VM add optimizations, your applications will get them for free, but static compiled programs would not).
    True, with C++ you only benefit from optimizations in the standard library without rebuilding the program, so it's a good reason for the big bad corporations that only release binary blobs, but you're talking to a Gentoo user here who is not scared of an `emerge -e world` after upgrading the toolchain

    Quote Originally Posted by ciplogic View Post
    You may try Jake2 game engine, and try the equivalent Quake2 demo, and tell me which is faster, as for my machine, Quake2/Java is faster than Quake2
    I am not familiar with Jake2, so I can only speculate on the possible reasons for that, ranging from Jake2 taking advantage of some newer features that were not available 15 years ago when the original Quake2 was written (like multithreading or maybe even newer OpenGL features) to some incompatibilities of Quake2 with newer OS versions, for example Diablo 2 runs like crap on Windows Vista or newer and it's only 12 years old.

    Quote Originally Posted by ciplogic View Post
    At the end, one very last cool thing Java/.Net world has, and C++ have harder times: to work with multiple (good) languages in parts of project and don't have "Invalid Read Address at 0x0ffaas5dda". I recommend to Kotlin (http://confluence.jetbrains.net/disp...etting+Started) which is Java based but brings some runtime warranties and is really nice to code in.
    So Kotlin tries to bring in features from C# and C++ while maintaining compatibility with JVM?

  6. #56
    Join Date
    Oct 2010
    Posts
    258

    Default

    Quote Originally Posted by ciplogic View Post
    Reddit-C++ page have a link one week ago, that states the same. And gave numbers how to improve 3x the reference counting, by removing the thread-save code.
    Well, their code is bogus, they increment/decrement the pointer to the counter, not the value itself. And you can only use their hack when you know multiple threads will never share a pointer, it's a lot better to make sure you only make a copy of the smart pointer when actually required to. In a multi threaded application there should be limited number of functions that are invoked on a different thread, and those function would take the smart pointer as value, while the rest of the functions as const reference.

  7. #57
    Join Date
    Nov 2009
    Location
    Madrid, Spain
    Posts
    304

    Default

    Quote Originally Posted by Ansla View Post
    The misuse is not using smart pointers in the first place, but not passing them as const reference on the function call. Because if the function called is only using the pointer for the duration of its life time, not taking ownership by storing a copy of the pointer at some global level why increment the usage counter? Lets say your function actually does store it for later reference, then the code would look like this:
    Code:
    void ProcessItem(const std::shared_ptr<Item> &item) {
        someOtherSmartPointer = item;
    }
    This code will work as the assignment operator for shared_ptr (both the C++11 version and the boost version) take a const reference as parameter. So passing the smart pointer as value instead of reference is a misuse, especially because it can be passed around for many times before some function actually stores it for later use (or maybe it won't be stored at all).
    If you use const & instead of raw pointer is really the same, and it miss the point of shared_ptr. This is why I told that is miss the point of shared pointer. Also having to enable a feature with performance implications means, so you use just minimally, means that users have to get extra thought if they want to use a feature or not, and they may not use it. And in Java you may get the performance right, and having the feature, when in C++ you may not have it, either the feature or the performance.

    Quote Originally Posted by Ansla View Post
    That depends a lot on the malloc implementation wrapped around by C++ new. And also the average C#/Java program will do a lot more dynamic memory allocations then a C++ one because in C++ it's possible to place a temporary instance of a class on the stack, with C#/Java you can only store on the stack primitive types, any class has to be dynamically allocated.
    I'm talking about default implementation/featureset. And if you use the same parameter for Java about Escape Analysis, it will convert heap allocations as stack allocations (as long the JIT can prove them safe). C# have "struct" keyword that put data on a stack, so there is nothing to complain on C# too.


    Quote Originally Posted by Ansla View Post
    But an array in C#/Java can not be resized, and the main reason for using C++ std::vector is it's ability to resize at runtime, so they are not at all equivalent
    Yet, they are not equivalent for other reasons too: arrays are allocated always on heap on VM languages too, but are closer equivalents than the Generic collections (at least on Java, as you noticed it, but also in C#, as the iteration will do every time a virtual call, as collections have to implement IEnumerable<T>)


    Quote Originally Posted by Ansla View Post
    True, with C++ you only benefit from optimizations in the standard library without rebuilding the program, so it's a good reason for the big bad corporations that only release binary blobs, but you're talking to a Gentoo user here who is not scared of an `emerge -e world` after upgrading the toolchain
    I think about the most users, they update the runtime when they update the OS/distribution. It seem to me you're not a Gentoo emerge guy, but even you would be one, I can say to you that Java was many times on the top of fast code, before GCC would catch up.
    Quote Originally Posted by Ansla View Post
    I am not familiar with Jake2, so I can only speculate on the possible reasons for that, ranging from Jake2 taking advantage of some newer features that were not available 15 years ago when the original Quake2 was written (like multithreading or maybe even newer OpenGL features) to some incompatibilities of Quake2 with newer OS versions, for example Diablo 2 runs like crap on Windows Vista or newer and it's only 12 years old.
    Jake2 is not faster as of OpenGL rewrite, but it would make sense even it would happen for this reason, but also because Java code can be sometimes optimized more today that a lot of C pointers code may be.

    Quote Originally Posted by Ansla View Post
    So Kotlin tries to bring in features from C# and C++ while maintaining compatibility with JVM?
    It brings (maybe) some features of C#, but most likely the source was Scala and other JVM languages, but I did not see any C++, the single reference in their FAQ page is:
    Consider, for instance, the chaos that existed in C++ with the wide variety of different 'custom' types created to hold booleans before the language designers finally added a standard 'bool' type to the language in an attempt to control the chaos.

  8. #58
    Join Date
    Nov 2009
    Location
    Madrid, Spain
    Posts
    304

    Default

    Quote Originally Posted by Ansla View Post
    The misuse is not using smart pointers in the first place, but not passing them as const reference on the function call. Because if the function called is only using the pointer for the duration of its life time, not taking ownership by storing a copy of the pointer at some global level why increment the usage counter? Lets say your function actually does store it for later reference, then the code would look like this:
    Code:
    void ProcessItem(const std::shared_ptr<Item> &item) {
        someOtherSmartPointer = item;
    }
    This code will work as the assignment operator for shared_ptr (both the C++11 version and the boost version) take a const reference as parameter. So passing the smart pointer as value instead of reference is a misuse, especially because it can be passed around for many times before some function actually stores it for later use (or maybe it won't be stored at all).
    Source
    :
    Code:
    std::shared_ptr<std::string> previous_message;
    
    void send_message(const std::shared_ptr<std::string> &msg)
    {
        previous_message = 0;
        std::cout << *msg << std::endl;
        previous_message = msg;
    }
    (...)
    send_message(std::shared_ptr<std::string>(new std::string("Hi")));
    send_message(previous_message);
    This would crash! I'm not saying that in places where you "obviously know" that the shared pointer cannot be null, to not use the const& construct, but you are basically on your own when you work with const references! So be aware, and use the principle: "the root of all evil is premature optimization".

  9. #59
    Join Date
    Oct 2010
    Posts
    258

    Default

    Quote Originally Posted by ciplogic View Post
    If you use const & instead of raw pointer is really the same, and it miss the point of shared_ptr.
    Not at all, the const reference to a shared_ptr is all you need in order to increment the usage count of the existing shared_ptr. While having only a raw pointer you could only create a shared_ptr with a distinct counter and the original shared_ptr would free the pointer making your band new shared_ptr hold a dangling pointer.

    Code:
    #include <memory>
    #include <iostream>
    
    std::shared_ptr<int> x;
    std::shared_ptr<int> y;
    
    void updatex(const std::shared_ptr<int> &newX) {
            x = newX;
    }
    
    void updatey(int *newY) {
            y = std::shared_ptr<int>(newY);
    }
    
    int main() {
            {
                    std::shared_ptr<int> tmpx(new int(1));
                    std::shared_ptr<int> tmpy(new int(2));
                    updatex(tmpx);
                    updatey(tmpy.get());
                    std::cout << "tmpx=" << *tmpx << std::endl;
                    std::cout << "tmpy=" << *tmpy << std::endl;
            }
            std::cout << "x=" << *x << std::endl;
            std::cout << "y=" << *y << std::endl;
    
            return 0;
    }
    I was hoping for a crash, but I wasn't so lucky But running it with valgrind I got:
    Code:
    tmp=1
    tmp2=2
    x=1
    ==32677== Invalid read of size 4
    ==32677==    at 0x401215: main (in /home/andrei/Projects/smart_pointers/a.out)
    ==32677==  Address 0x59790f0 is 0 bytes inside a block of size 4 free'd
    ==32677==    at 0x4C28A5E: operator delete(void*) (vg_replace_malloc.c:387)
    ==32677==    by 0x401330: main (in /home/andrei/Projects/smart_pointers/a.out)
    ==32677== 
    y=2
    ==32677== Invalid free() / delete / delete[]
    ==32677==    at 0x4C28A5E: operator delete(void*) (vg_replace_malloc.c:387)
    ==32677==    by 0x401578: std::shared_ptr<int>::~shared_ptr() (in /home/andrei/Projects/smart_pointers/a.out)
    ==32677==    by 0x560D870: exit (in /lib64/libc-2.13.so)
    ==32677==    by 0x55F50A3: (below main) (in /lib64/libc-2.13.so)
    ==32677==  Address 0x59790f0 is 0 bytes inside a block of size 4 free'd
    ==32677==    at 0x4C28A5E: operator delete(void*) (vg_replace_malloc.c:387)
    ==32677==    by 0x401330: main (in /home/andrei/Projects/smart_pointers/a.out)
    So not only y holds a dangling pointer that might point to a random value, but it will also try to free the pointer a second time! While x correctly took over ownership from tmpx.

    Quote Originally Posted by ciplogic View Post
    I think about the most users, they update the runtime when they update the OS/distribution. It seem to me you're not a Gentoo emerge guy, but even you would be one, I can say to you that Java was many times on the top of fast code, before GCC would catch up.
    I probably think in "proprietary world" (Windows/MacOS X) terms, where you have lots of 3rdParty apps installed that will not be updated together with the OS. But for a regular Linux distribution an OS update would also bring all the apps rebuilt with the new toolchain.

    Quote Originally Posted by ciplogic View Post
    Jake2 is not faster as of OpenGL rewrite, but it would make sense even it would happen for this reason, but also because Java code can be sometimes optimized more today that a lot of C pointers code may be.
    Again, if your comparing a C binary from 15 years ago with a Java program running on a recent version of JRE, Java will have an advantage. As you said above, the Java program will take advantage of the new JVM while the C blob is forever stuck in 1997. And I'm sure the Java code being more recent also helps, I doubt if Jake2 was written in 1997 (using JDK 1.0 or 1.1 whatever was the current version at that time!!!), it would perform the same.

    Quote Originally Posted by ciplogic View Post
    It brings (maybe) some features of C#, but most likely the source was Scala and other JVM languages, but I did not see any C++, the single reference in their FAQ page is:
    It might be a feature of Scala, I don't think i even heard of that language before, but it's also in C++... "Operator overloading" on this page http://confluence.jetbrains.net/disp...arison+to+Java

  10. #60
    Join Date
    Nov 2009
    Location
    Madrid, Spain
    Posts
    304

    Default

    Quote Originally Posted by Ansla View Post
    Not at all, the const reference to a shared_ptr is all you need in order to increment the usage count of the existing shared_ptr. While having only a raw pointer you could only create a shared_ptr with a distinct counter and the original shared_ptr would free the pointer making your band new shared_ptr hold a dangling pointer.

    Code:
    (...)
    You misunderstood the problem,
    The problem is when you have side effects, and try this:
    Code:
    #include <memory>
    #include <iostream>
    
    std::shared_ptr<int> x;
    void resetX() {
      x = std::shared_ptr<int> (0);
    }
    
    void updatex(const std::shared_ptr<int> &newX) {
    	resetX(); //code have side effects that do set the 
    //reference count of X to zero
           //the referene to newX is wrong
            std::cout << "x=" << newX << std::endl;
    }
    void updatex_safe_and_slow(std::shared_ptr<int> newX) {
    	resetX(); //code have side effects that do set the 
    //reference count of X to zero, but you have still a safe copy
            std::cout << "x=" << newX << std::endl;
    }
    
    
    void main() {
           {
    x =std::shared_ptr<int> (new int(1));
                    updatex_safe_and_slow(x);
                    
            }
      
           {
    x =std::shared_ptr<int> (new int(1));
                    updatex(x);
                    
            }
    }
    I cannot compile on Gcc now, may you try to reproduce if you have a crash? (I think that you should, and I'm not talking about dangling pointers, which is fun to have in your application )

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •