Hard question: Any ideas why this code leaks memory?

Discussion in 'Ruby' started by Sven C. Koehler, Aug 19, 2008.

  1. Hello,

    could someone help me understand why this code leaks memory? (I am using
    ruby 1.8.6 (2007-12-03 patchlevel 113) [x86_64-linux].)

    def rss_leaks
    /^VmRSS:\s+(\d+)/m.match(File.open("/proc/#{$$}/status") {|f|
    f.read })[1].to_i
    end

    | irb(main):002:0> 100000.times { rss_leaks }; rss_leaks
    | => 11624
    | irb(main):003:0> 100000.times { rss_leaks }; rss_leaks
    | => 16836
    | irb(main):004:0> 100000.times { rss_leaks }; rss_leaks
    | => 22008
    | irb(main):005:0> 100000.times { rss_leaks }; rss_leaks
    | => 27248
    | irb(main):006:0> 100000.times { rss_leaks }; rss_leaks
    | => 32468

    Calling GC.start inbetween does not help, but when we rewrote rss_leaks
    this way the leaks disappeared:

    def rss_no_leaks()
    d = File.open("/proc/#{$$}/status") {|f| f.read }
    /^VmRSS:\s+(\d+)/m.match(d)[1].to_i
    end

    | irb(main):002:0> 100000.times { rss_no_leaks }; rss_no_leaks
    | => 6568
    | irb(main):003:0> 100000.times { rss_no_leaks }; rss_no_leaks
    | => 6568
    | irb(main):004:0> 100000.times { rss_no_leaks }; rss_no_leaks
    | => 6588
    | irb(main):005:0> 100000.times { rss_no_leaks }; rss_no_leaks
    | => 6592
    | irb(main):006:0> 100000.times { rss_no_leaks }; rss_no_leaks
    | => 6572

    Any help to further understand what actually causes these leaks would be
    very appreaciated!

    Best wishes,

    Sven
     
    Sven C. Koehler, Aug 19, 2008
    #1
    1. Advertisements

  2. Sven C. Koehler

    Xavier Noria Guest

    No idea about the leak, just wanted to point out for the archives that
    /m does nothing there because there's no dot.

    /m in Ruby is /s in Perl ("." matches "\n"), and Perl's /m (multi-line
    mode) is always on in Ruby, there's no way to switch that one off. ^
    is always beginning of line, and you assert beginning of string with
    \A. To tangle this a little more /s in Ruby exists and means the
    regexp is written in the SJIS encoding.
     
    Xavier Noria, Aug 20, 2008
    #2
    1. Advertisements

  3. Hi,

    At Wed, 20 Aug 2008 04:46:24 +0900,
    Sven C. Koehler wrote in [ruby-talk:311847]:
    Seems a bug.
     
    Nobuyoshi Nakada, Aug 20, 2008
    #3
  4. Sven C. Koehler, Aug 20, 2008
    #4
  5. Nobuyoshi Nakada, Aug 20, 2008
    #5
  6. I tried some of the patches mentioned on the page on my ruby-1.8.6, and this is
    the patch which worked for me (saves me some time before upgrading to 1.8.7).

    -S.

    --- parse.old.y 2008-08-20 10:59:56.000000000 +0000
    +++ parse.y 2008-08-20 11:08:16.000000000 +0000
    @@ -5716,7 +5716,7 @@
    rb_mem_clear(vars+i, len-i);
    }
    else {
    - *vars++ = (VALUE)ruby_scope;
    + *vars++ = 0;
    rb_mem_clear(vars, len);
    }
    ruby_scope->local_vars = vars;
    @@ -5732,6 +5732,7 @@
    if (!(ruby_scope->flags & SCOPE_CLONE))
    xfree(ruby_scope->local_tbl);
    }
    + ruby_scope->local_vars[-1] = 0; /* no reference needed */
    ruby_scope->local_tbl = local_tbl();
    }
    }
     
    Sven C. Koehler, Aug 20, 2008
    #6
  7. Hi,

    At Wed, 20 Aug 2008 20:19:43 +0900,
    Sven C. Koehler wrote in [ruby-talk:311956]:
    It has been applied to the latest 1.8, of course.
     
    Nobuyoshi Nakada, Aug 20, 2008
    #7
    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.