Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid lock when ecs_compatibility is explicitly specified #16786

Merged
merged 1 commit into from
Dec 19, 2024

Conversation

yaauie
Copy link
Member

@yaauie yaauie commented Dec 11, 2024

Release notes

  • Improves concurrent performance of some plugins when they are instantiated with an explicit ecs_compatibility directive.

What does this PR do?

Properly memoizes an explicitly-given ecs_compatibility directive on first access so that it can be retrieved without lock contention.

Because a break escapes a begin...end block, we must not use a break in order to ensure that the explicitly set value gets memoized to avoid lock contention.

def fake_sync(&block)
  puts "FAKE_SYNC:enter"
  val = yield
  puts "FAKE_SYNC:return(#{val})"
  return val
ensure
  puts "FAKE_SYNC:ensure"
end

returned = fake_sync do
  @ivar = begin
    puts("BE:begin")
    break :break # expectation: break the current `begin`...`end` block
  	
    val = :returned
    puts("BE:return(#{val})")
    val
  ensure
    puts("BE:ensure")
  end
end
puts({:returned => returned, :@ivar => @ivar})

Note: no FAKE_SYNC:return:

╭─{ rye@perhaps:~/src/elastic/logstash (main ✔) }
╰─● ruby break-esc.rb
FAKE_SYNC:enter
BE:begin
BE:ensure
FAKE_SYNC:ensure
{:returned=>:break, :@ivar=>nil}
[success]

Why is it important/What is the impact to the user?

Eliminates unnecessary lock contention, which can prevent some plugins from running as concurrently as they would otherwise be able.

Checklist

  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • [ ] I have made corresponding changes to the documentation
  • [ ] I have made corresponding change to the default configuration files (and/or docker env variables)
  • [ ] I have added tests that prove my fix is effective or that my feature works

How to test this PR locally

Related issues

Use cases

Screenshots

Logs

Because a `break` escapes a `begin`...`end` block, we must not use a `break` in order to ensure that the explicitly set value gets memoized to avoid lock contention.

> ~~~ ruby
> def fake_sync(&block)
>   puts "FAKE_SYNC:enter"
>   val = yield
>   puts "FAKE_SYNC:return(#{val})"
>   return val
> ensure
>   puts "FAKE_SYNC:ensure"
> end
> 
> fake_sync do
>   @ivar = begin
>     puts("BE:begin")
>   	break :break
>   	
>   	val = :ret
>   	puts("BE:return(#{val})")
>   	val
>   ensure
>     puts("BE:ensure")
>   end
> end
> ~~~

Note: no `FAKE_SYNC:return`:

> ~~~
> ╭─{ rye@perhaps:~/src/elastic/logstash (main ✔) }
> ╰─● ruby break-esc.rb
> FAKE_SYNC:enter
> BE:begin
> BE:ensure
> FAKE_SYNC:ensure
> [success]
> ~~~
@yaauie yaauie added the bug label Dec 11, 2024
@yaauie yaauie requested a review from jsvd December 11, 2024 18:39
Copy link

Quality Gate passed Quality Gate passed

Issues
0 New issues
0 Fixed issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
No data about Duplication

See analysis details on SonarQube

@elasticmachine
Copy link
Collaborator

💚 Build Succeeded

Copy link
Member

@jsvd jsvd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@yaauie yaauie merged commit 01c8e8b into main Dec 19, 2024
7 checks passed
@yaauie yaauie deleted the yaauie-ecs-memoize-avoid-lock branch December 19, 2024 23:48
@yaauie
Copy link
Member Author

yaauie commented Dec 19, 2024

@logstashmachine backport 8.x

@yaauie
Copy link
Member Author

yaauie commented Dec 19, 2024

@logstashmachine backport 8.17

github-actions bot pushed a commit that referenced this pull request Dec 19, 2024
Because a `break` escapes a `begin`...`end` block, we must not use a `break` in order to ensure that the explicitly set value gets memoized to avoid lock contention.

> ~~~ ruby
> def fake_sync(&block)
>   puts "FAKE_SYNC:enter"
>   val = yield
>   puts "FAKE_SYNC:return(#{val})"
>   return val
> ensure
>   puts "FAKE_SYNC:ensure"
> end
>
> fake_sync do
>   @ivar = begin
>     puts("BE:begin")
>   	break :break
>
>   	val = :ret
>   	puts("BE:return(#{val})")
>   	val
>   ensure
>     puts("BE:ensure")
>   end
> end
> ~~~

Note: no `FAKE_SYNC:return`:

> ~~~
> ╭─{ rye@perhaps:~/src/elastic/logstash (main ✔) }
> ╰─● ruby break-esc.rb
> FAKE_SYNC:enter
> BE:begin
> BE:ensure
> FAKE_SYNC:ensure
> [success]
> ~~~

(cherry picked from commit 01c8e8b)
github-actions bot pushed a commit that referenced this pull request Dec 19, 2024
Because a `break` escapes a `begin`...`end` block, we must not use a `break` in order to ensure that the explicitly set value gets memoized to avoid lock contention.

> ~~~ ruby
> def fake_sync(&block)
>   puts "FAKE_SYNC:enter"
>   val = yield
>   puts "FAKE_SYNC:return(#{val})"
>   return val
> ensure
>   puts "FAKE_SYNC:ensure"
> end
>
> fake_sync do
>   @ivar = begin
>     puts("BE:begin")
>   	break :break
>
>   	val = :ret
>   	puts("BE:return(#{val})")
>   	val
>   ensure
>     puts("BE:ensure")
>   end
> end
> ~~~

Note: no `FAKE_SYNC:return`:

> ~~~
> ╭─{ rye@perhaps:~/src/elastic/logstash (main ✔) }
> ╰─● ruby break-esc.rb
> FAKE_SYNC:enter
> BE:begin
> BE:ensure
> FAKE_SYNC:ensure
> [success]
> ~~~

(cherry picked from commit 01c8e8b)
@yaauie
Copy link
Member Author

yaauie commented Dec 19, 2024

@logstashmachine backport 8.16

github-actions bot pushed a commit that referenced this pull request Dec 19, 2024
Because a `break` escapes a `begin`...`end` block, we must not use a `break` in order to ensure that the explicitly set value gets memoized to avoid lock contention.

> ~~~ ruby
> def fake_sync(&block)
>   puts "FAKE_SYNC:enter"
>   val = yield
>   puts "FAKE_SYNC:return(#{val})"
>   return val
> ensure
>   puts "FAKE_SYNC:ensure"
> end
>
> fake_sync do
>   @ivar = begin
>     puts("BE:begin")
>   	break :break
>
>   	val = :ret
>   	puts("BE:return(#{val})")
>   	val
>   ensure
>     puts("BE:ensure")
>   end
> end
> ~~~

Note: no `FAKE_SYNC:return`:

> ~~~
> ╭─{ rye@perhaps:~/src/elastic/logstash (main ✔) }
> ╰─● ruby break-esc.rb
> FAKE_SYNC:enter
> BE:begin
> BE:ensure
> FAKE_SYNC:ensure
> [success]
> ~~~

(cherry picked from commit 01c8e8b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants