Jira (PUP-11755) each/map/filter functions are slow/buggy on jruby

25 views
Skip to first unread message

Nick Lewis (Jira)

unread,
Feb 7, 2023, 6:18:03 PM2/7/23
to puppe...@googlegroups.com
Nick Lewis created an issue
 
Puppet / Bug PUP-11755
each/map/filter functions are slow/buggy on jruby
Issue Type: Bug Bug
Assignee: Unassigned
Created: 2023/02/07 3:17 PM
Priority: Normal Normal
Reporter: Nick Lewis

The each, map and filter functions use a pattern for enumeration that is both extremely slow and incorrect when run in jruby:

The pattern is roughly:

enum = object.each
 
object.size.times do
  yield(enum.next)
end

Because this only calls next as many times as there are objects in the enuemrator, it never triggers StopIteration. That causes the Fiber associated with the enumerator not to be cleaned up. Since JRuby Fibers are mapped to native threads, that leaves an active native thread, which can cause the server to hit its limit of threads. It also means the Fiber serves as a GC root, and so any objects referenced from it will remain uncollected.

A more correct pattern is:

enum = object.each
 
begin
  loop do
    yield(enum.next)
  end
rescue StopIteration
end

This avoids letting threads accumulate, but it's still very expensive. The most correct version is simply:

object.each do |value|
  yield(value)
end

I used the following example as a comparison:

a = 5000.times.map do
  {
    'one' => 'foo',
    'two' => 'bar',
    'three' => 'baz',
    'four' => 'quux',
  }.freeze
end
 
my_proc = proc do |(k,v)|
end
 
Benchmark.bm do |x|
  x.report do
    10.times.each do
      a.each do |h|
        h.each_pair do |pair|
          my_proc.call(pair)
        end
      end
    end
  end
 
  x.report do
    10.times.each do |i|
      a.each_with_index do |h, j|
        enum = h.each_pair
        begin
          loop do
            my_proc.call(enum.next)
          end
        rescue StopIteration
        end
      end
    end
  end
end

with the results

❯ ruby test.rb
       user     system      total        real
   0.030373   0.000491   0.030864 (  0.030925)
   0.217605   0.018319   0.235924 (  0.235980)
❯ jruby test.rb
       user     system      total        real
   0.800000   0.020000   0.820000 (  0.091818)
  20.310000   2.370000  22.680000 ( 17.027952)

In MRI, the difference is around an order of magnitude, but both versions are so fast the cost is negligible either way. On JRuby, the difference is >150x.

Add Comment Add Comment
 
This message was sent by Atlassian Jira (v8.20.11#820011-sha1:0629dd8)
Atlassian logo

Michael Hashizume (Jira)

unread,
Feb 8, 2023, 12:41:01 PM2/8/23
to puppe...@googlegroups.com

Gareth McGrillan (Jira)

unread,
Feb 13, 2023, 5:32:02 AM2/13/23
to puppe...@googlegroups.com
Gareth McGrillan commented on Bug PUP-11755
 
Re: each/map/filter functions are slow/buggy on jruby

Hi Nick Lewis  - do you have any idea when this might be in a release?
Gareth...

Josh Cooper (Jira)

unread,
Feb 14, 2023, 3:04:03 PM2/14/23
to puppe...@googlegroups.com
Josh Cooper updated an issue
 
Change By: Josh Cooper
Fix Version/s: PUP 7.24.0

Josh Cooper (Jira)

unread,
Feb 15, 2023, 2:59:02 AM2/15/23
to puppe...@googlegroups.com
Josh Cooper updated an issue
Change By: Josh Cooper
Epic Link: PUP-11658

Josh Cooper (Jira)

unread,
Feb 15, 2023, 11:47:03 AM2/15/23
to puppe...@googlegroups.com

Josh Cooper (Jira)

unread,
Feb 15, 2023, 12:08:02 PM2/15/23
to puppe...@googlegroups.com
Josh Cooper updated an issue
Change By: Josh Cooper
Sprint: Phoenix 2023-03-01

Michael Hashizume (Jira)

unread,
Feb 24, 2023, 2:26:02 PM2/24/23
to puppe...@googlegroups.com
Michael Hashizume commented on Bug PUP-11755
 
Re: each/map/filter functions are slow/buggy on jruby

Passed CI in puppet-agent#33e76d88addb3732db256683cb297b4849902798 / puppet#d6d631a2f5b38b756e2d5635731006ee519d53db

Nick Lewis (Jira)

unread,
Mar 9, 2023, 6:30:02 PM3/9/23
to puppe...@googlegroups.com
Nick Lewis updated an issue
 
Change By: Nick Lewis
Release Notes: Bug Fix

Nick Lewis (Jira)

unread,
Mar 9, 2023, 6:32:02 PM3/9/23
to puppe...@googlegroups.com
Nick Lewis updated an issue
Change By: Nick Lewis
Release Notes Summary: This fixes a case where the each/map/filter built-in functions in Puppet language had poor performance and consumed unnecessary resources.

Nick Lewis (Jira)

unread,
Mar 20, 2023, 5:15:02 PM3/20/23
to puppe...@googlegroups.com
Nick Lewis commented on Bug PUP-11755
 
Re: each/map/filter functions are slow/buggy on jruby

Ingrida Cazers Yes, it will be in those releases. That text looks right!

Parker Leach (Jira)

unread,
Apr 5, 2023, 5:59:01 PM4/5/23
to puppe...@googlegroups.com
Parker Leach updated an issue
 
Change By: Parker Leach
Labels: docs_reviewed

Ingrida Cazers (Jira)

unread,
Apr 10, 2023, 5:26:02 PM4/10/23
to puppe...@googlegroups.com
Ingrida Cazers updated an issue
Change By: Ingrida Cazers
Labels: docs docs_reviewed
Reply all
Reply to author
Forward
0 new messages