Skip to content

perf(etcd): refactor some code to improve performance#12011

Open
xuruidong wants to merge 4 commits intoapache:masterfrom
xuruidong:config-etcd
Open

perf(etcd): refactor some code to improve performance#12011
xuruidong wants to merge 4 commits intoapache:masterfrom
xuruidong:config-etcd

Conversation

@xuruidong
Copy link
Contributor

@xuruidong xuruidong commented Feb 28, 2025

Description

Fixes # (issue)

Before:
The original code performed a cleanup of self.values and rebuilt self.values_hash by:

  • Made a full copy of self.values
  • Cleared the original and reinserted non-nil values
  • Rebuilt values_hash in a separate step

Problems:

  • Wasted memory (copied entire table)
  • Slow (processed data twice)

Now:

  1. In-place cleanup:
    • Removes nil values while keeping the same table
    • Updates values_hash at the same time
  2. Trims empty space:
    • Deletes unused slots at the end

Why better?

  • Faster: Does everything in one pass
  • Uses less memory: No extra table copies
  • Works better for big datasets

Before:
The original code performed a cleanup of self.values and rebuilt self.values_hash by:

  • Made a full copy of self.values
  • Cleared the original and reinserted non-nil values
  • Rebuilt values_hash in a separate step

Problems:

  • Wasted memory (copied entire table)
  • Slow (processed data twice)

Now:

  1. In-place cleanup:
    • Removes nil values while keeping the same table
    • Updates values_hash at the same time
  2. Trims empty space:
    • Deletes unused slots at the end

Why better?

  • Faster: Does everything in one pass
  • Uses less memory: No extra table copies
  • Works better for big datasets

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible (If not, please discuss on the APISIX mailing list first)

Signed-off-by: xuruidong <xuruidong@gmail.com>
@dosubot dosubot bot added size:S This PR changes 10-29 lines, ignoring generated files. performance generate flamegraph for the current PR labels Feb 28, 2025
@juzhiyuan
Copy link
Member

@xuruidong Just approved to run the CI

@xuruidong
Copy link
Contributor Author

@xuruidong Just approved to run the CI

please run the CI again @juzhiyuan

@juzhiyuan
Copy link
Member

@xuruidong Just approved to run the CI

please run the CI again @juzhiyuan

Hi @xuruidong, I couldn't find the Re-run button. Can you confirm the failed test cases?

image

@xuruidong
Copy link
Contributor Author

I don't think the CI failure is related to the code changes.

@Baoyuantop
Copy link
Contributor

Hi @xuruidong, can you add some descriptive information for PR?

@Baoyuantop
Copy link
Contributor

Hi @xuruidong, please add a PR description so that others can review it better ~

@Baoyuantop Baoyuantop added the wait for update wait for the author's response in this issue/PR label Apr 29, 2025
@xuruidong
Copy link
Contributor Author

Hi @xuruidong, please add a PR description so that others can review it better ~

Hi @Baoyuantop , the PR description has been added, please help review it. Thanks.

@Baoyuantop Baoyuantop removed wait for update wait for the author's response in this issue/PR user responded labels Jun 16, 2025
@Baoyuantop
Copy link
Contributor

Please fix the failed ci

@xuruidong
Copy link
Contributor Author

Please fix the failed ci

Hi @Baoyuantop ,please trigger the ci

@xuruidong
Copy link
Contributor Author

Hi @Baoyuantop , the ci is not stable, the failed test should be rerun

@Baoyuantop
Copy link
Contributor

Hi @xuruidong, there are still bad CIs that need to be fixed.

@Baoyuantop
Copy link
Contributor

Hi @xuruidong, any updates?

@xuruidong
Copy link
Contributor Author

Hi @xuruidong, any updates?

Hi @Baoyuantop ,please trigger the ci

@github-actions
Copy link

This pull request has been marked as stale due to 60 days of inactivity. It will be closed in 4 weeks if no further activity occurs. If you think that's incorrect or this pull request should instead be reviewed, please simply write any comment. Even if closed, you can still revive the PR at any time or discuss it on the dev@apisix.apache.org list. Thank you for your contributions.

@github-actions github-actions bot added the stale label Sep 27, 2025
@Baoyuantop
Copy link
Contributor

Hi @xuruidong, are you still working on this pull request? There are some failed tests that need to be addressed.

@github-actions github-actions bot removed the stale label Sep 29, 2025
@xuruidong
Copy link
Contributor Author

Hi @xuruidong, are you still working on this pull request? There are some failed tests that need to be addressed.

Hi @Baoyuantop ,please trigger the CI

@github-actions
Copy link

github-actions bot commented Dec 9, 2025

This pull request has been marked as stale due to 60 days of inactivity. It will be closed in 4 weeks if no further activity occurs. If you think that's incorrect or this pull request should instead be reviewed, please simply write any comment. Even if closed, you can still revive the PR at any time or discuss it on the dev@apisix.apache.org list. Thank you for your contributions.

@github-actions
Copy link

This pull request has been marked as stale due to 60 days of inactivity. It will be closed in 4 weeks if no further activity occurs. If you think that's incorrect or this pull request should instead be reviewed, please simply write any comment. Even if closed, you can still revive the PR at any time or discuss it on the dev@apisix.apache.org list. Thank you for your contributions.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request optimizes the array compaction logic in the etcd configuration synchronization code to improve memory usage and performance. The optimization targets the cleanup routine that runs after 100+ deletions to remove stale entries from the values array.

Changes:

  • Added table.remove as a localized function remove_tab following codebase conventions
  • Refactored the array compaction algorithm to perform in-place compaction instead of copy-clear-rebuild
  • Combined values_hash rebuilding with array compaction into a single pass

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +811 to +812
local pre = 1
local cur = 1
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The variable names pre and cur are unclear and could be more descriptive. Consider renaming to write_idx and read_idx respectively to better convey their purpose in the compaction algorithm. write_idx represents the next position to write a valid element, while read_idx tracks the current position being read from the original array.

Copilot uses AI. Check for mistakes.
Comment on lines +811 to 828
local pre = 1
local cur = 1
table.clear(self.values_hash)
log.info("clear stale data in `values_hash` for key: ", key)
for _, val in ipairs(self.values) do
if val then
table.insert(self.values, val)
self.values[pre] = val
key = short_key(self, val.key)
self.values_hash[key] = pre
pre = pre + 1
end
end

table.clear(self.values_hash)
log.info("clear stale data in `values_hash` for key: ", key)
cur = cur + 1
end

for i = 1, #self.values do
key = short_key(self, self.values[i].key)
self.values_hash[key] = i
for i = cur - 1, pre, -1 do
remove_tab(self.values, i)
end
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The refactored array compaction logic (lines 811-828) lacks test coverage. This is a critical code path that triggers after 100 deletions to clean up the values array. Consider adding a test that creates multiple items, deletes them to increment sync_times beyond 100, and verifies the array is correctly compacted with no data corruption.

Copilot uses AI. Check for mistakes.
Comment on lines +812 to +826
local cur = 1
table.clear(self.values_hash)
log.info("clear stale data in `values_hash` for key: ", key)
for _, val in ipairs(self.values) do
if val then
table.insert(self.values, val)
self.values[pre] = val
key = short_key(self, val.key)
self.values_hash[key] = pre
pre = pre + 1
end
end

table.clear(self.values_hash)
log.info("clear stale data in `values_hash` for key: ", key)
cur = cur + 1
end

for i = 1, #self.values do
key = short_key(self, self.values[i].key)
self.values_hash[key] = i
for i = cur - 1, pre, -1 do
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The cur variable is only used to track the iteration count and could be replaced with #self.values captured before the loop. For example: local original_len = #self.values before line 815, then use original_len instead of cur - 1 in line 826. This would eliminate the need for incrementing cur on every iteration and make the code slightly clearer.

Copilot uses AI. Check for mistakes.
Comment on lines +818 to +819
key = short_key(self, val.key)
self.values_hash[key] = pre
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

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

The variable key shadows the outer loop variable declared at line 726. While this doesn't cause incorrect behavior since key is reassigned at the start of each outer loop iteration, it's poor practice and reduces code clarity. Consider using a different variable name such as item_key or short_k for the inner usage.

Suggested change
key = short_key(self, val.key)
self.values_hash[key] = pre
local item_key = short_key(self, val.key)
self.values_hash[item_key] = pre

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance generate flamegraph for the current PR size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants