Skip to content

Conversation

spuun
Copy link
Contributor

@spuun spuun commented Aug 18, 2025

Log::Metadata write its entries in the beginning of the allocated memory for all entries. When extending parent entries are prepended to the memory.

This will change so entries are written to the end of allocated memory to make it possible to write parent entries first when extending the Metadata instance. #defrag will move the "local" entries to the end of the parent entries or overwrite any existing parent entry for the current key.

Fixes #13360

This will reduce elements that needs to be copied to only
non-overwritten parent elements.

One result of this is that an overwritten parent entry will be moved
from the "parent" part of the Metadata to the "own" part. E.g.

`{a: 1, b: 2} extend {a: 3}` results in `{b: 2, a:3}`
@spuun spuun force-pushed the log-metadata-extend branch from 779ff50 to e31c739 Compare August 19, 2025 06:34
@spuun spuun requested a review from straight-shoota August 19, 2025 06:47
Comment on lines 48 to 49
parent_size = (@parent.try(&.max_total_size) || 0)
@max_total_size = @size + parent_size
Copy link
Member

Choose a reason for hiding this comment

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

polish: The variable parent_size is a bit unfortunate to have the same name as @parent_size, but the two differ semantically. Maybe we can rename this to parent_max_total_size or just inline it back as it was before. We don't necessarily need this variable.

#
# * @parent.nil? signals if the defrag is needed/done
# * The values of @overridden_size, pointerof(@first) are never changed
# * The value of pointerof(@first) are never changed
Copy link
Member

@straight-shoota straight-shoota Sep 4, 2025

Choose a reason for hiding this comment

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

Suggested change
# * The value of pointerof(@first) are never changed
# * The value of pointerof(@first) never changes.

Comment on lines 110 to 117
overwritten = false
@size.times do |i|
if ptr_entries[i][:key] == key
overridden = true
overwritten = true
break
end
end

unless overridden
next_free_entry.value = {key: key, value: value}
next_free_entry += 1
total_size += 1
end
next if overwritten
Copy link
Member

Choose a reason for hiding this comment

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

polish: I believe this can be simplified to a single #any? call.

Suggested change
overwritten = false
@size.times do |i|
if ptr_entries[i][:key] == key
overridden = true
overwritten = true
break
end
end
unless overridden
next_free_entry.value = {key: key, value: value}
next_free_entry += 1
total_size += 1
end
next if overwritten
overwritten = Slice.new(ptr_entries, @size).any? { |entry| entry[:key] == key}
next if overwritten

Comment on lines 136 to 139
parent_size.times do |i|
entry = ptr_entries[i + local_size]
yield({entry[:key], entry[:value]})
end
Copy link
Member

@straight-shoota straight-shoota Sep 4, 2025

Choose a reason for hiding this comment

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

suggestion: The local_size offset is static, so we could pull this addition out of the loop.
I'm not sure if this would have any significant performance impact. But it shouldn't hurt either.

Also we can generally simplify using Slice#each. I don't think this should have any performance impact over iterating the pointer indices directly.

Suggested change
parent_size.times do |i|
entry = ptr_entries[i + local_size]
yield({entry[:key], entry[:value]})
end
Slice.new(ptr_entries + local_size, parent_size).each do |entry|
yield({entry[:key], entry[:value]})
end

Copy link

@mverzilli mverzilli left a comment

Choose a reason for hiding this comment

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

LGTM

@ysbaddaden
Copy link
Contributor

@spuun there are a number of changes pending.

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.

Log::Metadata#extend should append not prepend data (like e.g. NamedTuple#merge)
4 participants