Skip to content

Dalli::Quantize performance regression in Rails 6.1+ #2997

Open

Description

Current behaviour
Rails 6.1 added a payload to the cache fetches.

The payload ultimately gets passed along to Dalli::Quantize.format_command in the *args.

.format_command is the following:

def format_command(operation, args)
  placeholder = "#{operation} BLOB (OMITTED)"
  command = [operation, *args].join(' ').strip
  command = Core::Utils.utf8_encode(command, binary: true, placeholder: placeholder)
  Core::Utils.truncate(command, Ext::QUANTIZE_MAX_CMD_LENGTH)
rescue => e
  Datadog.logger.debug("Error sanitizing Dalli operation: #{e}")
  placeholder
end

The performance regression occurs on the following line:

command = [operation, *args].join(' ').strip

If we end up with a hash in the payload the .join(' ') method can end up being incredible slow.

Expected behaviour

Same performance as Rails 6.0.

Steps to reproduce

Calling join on an array that contains a hash will end up calling inspect on the values in the hash. This is a particular problem when the objects define their own inspect method:

class Foo
  def inspect
    "something_slow"
  end
end

["bar", {baz: Foo.new}].join(" ") => "bar {:baz=>something_slow}"

Our current workaround is to reject hashes from the payload (which should be fine because prior to Rails 6.1 we weren't passing the payload to the tracing anyway:

module DatadogDalliQuantize
  def format_command(operation, args)
    string_args = args.reject { |arg| arg.is_a?(Hash) }
    super(operation, string_args)
  end
end

Datadog::Tracing::Contrib::Dalli::Quantize.singleton_class.prepend(DatadogDalliQuantize)

This works for us but we're not sure if it's best to have dd-trace-rb reject all hashes or not. 🤷

How does ddtrace help you?

Environment

  • ddtrace version: v1.12.1
  • Configuration block (Datadog.configure ...):
  • Ruby version: 3.2.2
  • Operating system: All OSes
  • Relevant library versions:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

bugInvolves a bugcommunityWas opened by a community memberintegrationsInvolves tracing integrations

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions