The Intellectual Wilderness There is nothing more useless than doing efficiently that which should not be done at all.

2021.04.30 09:10

Valgrind “Hello, World!”: Python 3.6 VS Python 2.7 VS Erlang R23

I’ll just leave this here…

Python 3.6

ceverett@icecream:~/Code/python$ cat hello.py
#! /usr/bin/python3

print("Hello, world!")
ceverett@icecream:~/Code/python$ ./hello.py
Hello, world!
ceverett@icecream:~/Code/python$ valgrind ./hello.py
...
==19264== HEAP SUMMARY:
==19264==     in use at exit: 320,946 bytes in 166 blocks
==19264==   total heap usage: 1,698 allocs, 1,532 frees, 2,505,946 bytes allocated
==19264== 
==19264== LEAK SUMMARY:
==19264==    definitely lost: 0 bytes in 0 blocks
==19264==    indirectly lost: 0 bytes in 0 blocks
==19264==      possibly lost: 5,608 bytes in 10 blocks
==19264==    still reachable: 315,338 bytes in 156 blocks
==19264==         suppressed: 0 bytes in 0 blocks
...
==19264== ERROR SUMMARY: 8163 errors from 116 contexts (suppressed: 0 from 0)
ceverett@icecream:~/Code/python$

Python 2.7

ceverett@icecream:~/Code/python$ cat hello2.py 
#! /usr/bin/python

print "Hello, world!"
ceverett@icecream:~/Code/python$ ./hello2.py
Hello, world!
ceverett@icecream:~/Code/python$ valgrind ./hello2.py
...
==19416== HEAP SUMMARY:
==19416==     in use at exit: 417,246 bytes in 199 blocks
==19416==   total heap usage: 2,958 allocs, 2,759 frees, 3,085,205 bytes allocated
==19416== 
==19416== LEAK SUMMARY:
==19416==    definitely lost: 0 bytes in 0 blocks
==19416==    indirectly lost: 0 bytes in 0 blocks
==19416==      possibly lost: 528 bytes in 1 blocks
==19416==    still reachable: 416,718 bytes in 198 blocks
==19416==         suppressed: 0 bytes in 0 blocks
...
==19416== ERROR SUMMARY: 489 errors from 30 contexts (suppressed: 0 from 0)
ceverett@icecream:~/Code/python$

Erlang R23

(On this one I can include the entire output.)

ceverett@icecream:~/Code/erlang$ cat hello_world 
#! /usr/bin/env escript

% Example of an escript
-mode(compile).

main(_) ->
    ok = io:setopts([{encoding, unicode}]),
    io:format("Hello, world!~n").
ceverett@icecream:~/Code/erlang$ ./hello_world 
Hello, world!
ceverett@icecream:~/Code/erlang$ valgrind ./hello_world
==25872== Memcheck, a memory error detector
==25872== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==25872== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==25872== Command: ./hello_world
==25872== 
Hello, world!
ceverett@icecream:~/Code/erlang$

Hey, Python! What the actual fsck is going on here?!? Jeebus… The Good Idea Fairy came along and convinced the webtarded among you to start throwing kitchen sink features in (“walrus operator” — yeah, great idea, that, and totally worth losing the sober guidance of Guido over…) along with 8163 memory errors. Sweet! Oh how far the great have fallen…

Honorable mention: Ruby 2.5

I didn’t expect much better from Ruby as the Good Idea Fairy has been forwarding all xer mail there for years, but wow… just wow

ceverett@icecream:~/Code/ruby$ cat hello_world.rb 
#! /usr/bin/ruby

print "Hello, World!\n"
ceverett@icecream:~/Code/ruby$ ./hello_world.rb 
Hello, World!
ceverett@icecream:~/Code/ruby$ valgrind ./hello_world.rb
...
==27051== HEAP SUMMARY:
==27051==     in use at exit: 2,921,234 bytes in 20,690 blocks
==27051==   total heap usage: 65,312 allocs, 44,622 frees, 16,447,358 bytes allocated
==27051== 
==27051== LEAK SUMMARY:
==27051==    definitely lost: 385,479 bytes in 4,421 blocks
==27051==    indirectly lost: 640,953 bytes in 5,808 blocks
==27051==      possibly lost: 1,626,429 bytes in 9,663 blocks
==27051==    still reachable: 268,373 bytes in 798 blocks
==27051==         suppressed: 0 bytes in 0 blocks
...
==27051== ERROR SUMMARY: 162050 errors from 402 contexts (suppressed: 0 from 0)
ceverett@icecream:~/Code/ruby$

162,050 memory errors. For Hello, World. How can there even be 162,050 instructions in the resulting set of commands to the system?

8 Comments »

  1. hello.lua:
    print("Hello World")
    
    valgrind lua hello.lua
    ==12708== Memcheck, a memory error detector
    ==12708== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==12708== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
    ==12708== Command: lua hello.lua
    ==12708==
    Hello World
    ==12708==
    ==12708== HEAP SUMMARY:
    ==12708==     in use at exit: 0 bytes in 0 blocks
    ==12708==   total heap usage: 325 allocs, 325 frees, 34,194 bytes allocated
    ==12708==
    ==12708== All heap blocks were freed -- no leaks are possible
    ==12708==
    ==12708== For lists of detected and suppressed errors, rerun with: -s
    ==12708== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

    The same program happens to work for Perl:

    valgrind perl hello.lua
    ==12925== Memcheck, a memory error detector
    ==12925== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==12925== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
    ==12925== Command: perl hello.lua
    ==12925==
    Hello World==12925==
    ==12925== HEAP SUMMARY:
    ==12925==     in use at exit: 192,435 bytes in 887 blocks
    ==12925==   total heap usage: 1,140 allocs, 253 frees, 243,067 bytes allocated
    ==12925==
    ==12925== LEAK SUMMARY:
    ==12925==    definitely lost: 7,942 bytes in 28 blocks
    ==12925==    indirectly lost: 44,520 bytes in 15 blocks
    ==12925==      possibly lost: 139,633 bytes in 843 blocks
    ==12925==    still reachable: 340 bytes in 1 blocks
    ==12925==         suppressed: 0 bytes in 0 blocks
    ==12925== Rerun with --leak-check=full to see details of leaked memory
    ==12925==
    ==12925== For lists of detected and suppressed errors, rerun with: -s
    ==12925== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

    Also for Julia (and this is a disaster):

    valgrind julia hello.lua
    ==13160== Memcheck, a memory error detector
    ==13160== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==13160== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
    ==13160== Command: julia hello.lua

    ~~~ Shitload of errors about invalid reads (past variables end), accesses to uninitialized data and such

    Hello World==13160== Warning: client switching stacks?  SP change: 0x1ffeffcc48 --> 0x56351ff8
    ==13160==          to suppress, use: --max-stackframe=135975840848 or greater
    --13160-- WARNING: unhandled amd64-linux syscall: 1008
    --13160-- You may be able to write your own handler.
    --13160-- Read the file README_MISSING_SYSCALL_OR_IOCTL.
    --13160-- Nevertheless we consider this a bug.  Please report
    --13160-- it at http://valgrind.org/support/bug_reports.html.
    ==13160== Warning: client switching stacks?  SP change: 0x56351918 --> 0x1ffeffcc50
    ==13160==          to suppress, use: --max-stackframe=135975842616 or greater
    ==13160==
    ==13160== HEAP SUMMARY:
    ==13160==     in use at exit: 98,046,061 bytes in 12,963 blocks
    ==13160==   total heap usage: 28,734 allocs, 15,771 frees, 101,648,745 bytes allocated
    ==13160==
    ==13160== LEAK SUMMARY:
    ==13160==    definitely lost: 1,144 bytes in 35 blocks
    ==13160==    indirectly lost: 0 bytes in 0 blocks
    ==13160==      possibly lost: 12,721 bytes in 96 blocks
    ==13160==    still reachable: 98,032,196 bytes in 12,832 blocks
    ==13160==                       of which reachable via heuristic:
    ==13160==                         newarray           : 47,464 bytes in 7 blocks
    ==13160==                         multipleinheritance: 6,912 bytes in 14 blocks
    ==13160==         suppressed: 0 bytes in 0 blocks
    ==13160== Rerun with --leak-check=full to see details of leaked memory
    ==13160==
    ==13160== Use --track-origins=yes to see where uninitialised values come from
    ==13160== For lists of detected and suppressed errors, rerun with: -s
    ==13160== ERROR SUMMARY: 19 errors from 8 contexts (suppressed: 0 from 0)

    Comment by Paweł Kraszewski — 2021.04.30 15:17 @ 15:17

  2. Julia?!? Oh noes! But you were the chosen one!
    These are quite a lot of fun to play around with.

    A friend found the same thing as you when testing Perl. I just wish Perl’s syntax was as clean as its runtime’s memory allocation practices!

    Comment by zxq9 — 2021.04.30 17:55 @ 17:55

  3. To test Python with valgrind you have to enable the malloc allocator:

    PYTHONMALLOC=malloc valgrind /usr/bin/python test.py
    ==822331== Memcheck, a memory error detector
    ==822331== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==822331== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
    ==822331== Command: /usr/bin/python test.py
    ==822331==
    Hello World!
    ==822331==
    ==822331== HEAP SUMMARY:
    ==822331==     in use at exit: 768,049 bytes in 6,313 blocks
    ==822331==   total heap usage: 59,448 allocs, 53,135 frees, 9,505,418 bytes allocated
    ==822331==
    ==822331== LEAK SUMMARY:
    ==822331==    definitely lost: 0 bytes in 0 blocks
    ==822331==    indirectly lost: 0 bytes in 0 blocks
    ==822331==      possibly lost: 761,074 bytes in 6,259 blocks
    ==822331==    still reachable: 6,975 bytes in 54 blocks
    ==822331==         suppressed: 0 bytes in 0 blocks
    ==822331== Rerun with --leak-check=full to see details of leaked memory
    ==822331==
    ==822331== For lists of detected and suppressed errors, rerun with: -s
    ==822331== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

    See https://docs.python.org/3/using/cmdline.html#envvar-PYTHONMALLOC

    Comment by Luper Rouch — 2021.04.30 16:10 @ 16:10

  4. Interesting! With my installation (Ubuntu’s build of 3.6.9) the output has changed to:

    ceverett@icecream:~/Code/python$ PYTHONMALLOC=malloc valgrind /usr/bin/python3 ./hello.py
    ...
    ==3365== HEAP SUMMARY:
    ==3365==     in use at exit: 883,912 bytes in 7,177 blocks
    ==3365==   total heap usage: 34,251 allocs, 27,074 frees, 5,086,061 bytes allocated
    ==3365== 
    ==3365== LEAK SUMMARY:
    ==3365==    definitely lost: 0 bytes in 0 blocks
    ==3365==    indirectly lost: 0 bytes in 0 blocks
    ==3365==      possibly lost: 354,878 bytes in 2,300 blocks
    ==3365==    still reachable: 529,034 bytes in 4,877 blocks
    ==3365==         suppressed: 0 bytes in 0 blocks
    ==3365== Rerun with --leak-check=full to see details of leaked memory
    ==3365== 
    ==3365== For counts of detected and suppressed errors, rerun with: -v
    ==3365== Use --track-origins=yes to see where uninitialised values come from
    ==3365== ERROR SUMMARY: 7296 errors from 10 contexts (suppressed: 0 from 0)
    


    Which build of Python are you testing?

    Comment by zxq9 — 2021.04.30 17:51 @ 17:51

  5. Thank you. Excellent visualization of today state of affairs in complang land …

    I’m lately in loved with Elixir (BEAM, Erlang ;-).

    Am asking for a friend, how about Java? Is Java doing any better?

    Comment by Jadran Prodan — 2021.04.30 16:13 @ 16:13

  6. Java… the OpenJDK seems to be a bit of a problem child in this regard. The Oracle and IBM JVMs I have not tested so I can’t say. I assume Oracle would sue me if I checked it, as litigation is their main business now, and IBM would probably rope me into a $10k/month perpetual contract — so I’m holding off.

    Comment by zxq9 — 2021.04.30 17:56 @ 17:56

  7. For this program that literally does nothing

    
    public class Blank
    {
        public static void main(String[] args)
        {
            return;
        }
    }

    
    ==29944== ERROR SUMMARY: 623989 errors from 219 contexts (suppressed: 0 from 0)
    

    we have.. six hundred and twenty three thousand, nine hundred and
    eighty nine errors.

    Let’s try Hello World

    
    public class Hello
    {
        public static void main(String[] args)
        {
            System.out.printf("hello world\n");
        }
    }
    

    
    ==30941== ERROR SUMMARY: 911980 errors from 242 contexts (suppressed: 0 from 0)
    

    nine hundred and eleven thousand, nine hundred and eighty errors.

    FizzBuzz

    
    public class FizzBuzz
    {
        static boolean divisibleBy(int n, int by)
        {
            return ((n % by) == 0);
        }
    
        public static void main(String[] args)
        {
            int i;
            for (i = 1; i <= 20; ++i)
            {
                if (divisibleBy(i, 15))
                    System.out.printf("FizzBuzz\n");
                else if (divisibleBy(i, 5))
                    System.out.printf("Buzz\n");
                else if (divisibleBy(i, 3))
                    System.out.printf("Fizz\n");
                else
                    System.out.printf("%d\n", i);
            }
        }
    }
    

    
    ==30706== ERROR SUMMARY: 826646 errors from 288 contexts (suppressed: 0 from 0)
    

    Only… eight hundred and twenty six thousand, six hundred and
    forty-six errors. So we’re down from hello world. I mean Hello World
    is pretty hard.

    Oh and since you asked, Elixir is for faggots.

    Comment by Craig Cannon — 2021.05.2 09:00 @ 09:00

  8. WOW! That’s a lot of errors… Fortunately I don’t have to deal with Java.
    And yes:

    true = (Erlang + ZX) > (Erlang + rebar) and (Erlang + ZX) > (Elixir + Anything)

    It is known. Well, only known to a handful of people because very few people research or try a new thing if it isn’t pumped on YouTube by a fake programmer paid by AWS/Google/Apple/MS who hates everything because he realizes for the first time as a paid shill that everything popular is retarded and built on fake paid hype…

    Nadir Dabit’s new video (which he dropped immediately after quitting his job as a paid AWS shill, er “developer advocate”) is instructive:

    Epic.

    Anyway… Java is like junk food, produced by smart people for consumption by masses of people less intelligent than them.

    Comment by zxq9 — 2021.05.2 14:11 @ 14:11

RSS feed for comments on this post.

Leave a comment

Powered by WordPress