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

GH-43129: [C++][Compute] Fix the unnecessary allocation of extra bytes when encoding row table #43125

Merged
merged 7 commits into from
Jul 10, 2024

Conversation

zanmato1984
Copy link
Contributor

@zanmato1984 zanmato1984 commented Jul 3, 2024

Rationale for this change

As described in #43129 , current row table occupies more memory than expected. The memory consumption is double of necessary. The reason listed below.

When encoding var length columns into into the row table:

RETURN_NOT_OK(
rows->AppendEmpty(static_cast<uint32_t>(num_selected), static_cast<uint32_t>(0)));
EncoderOffsets::GetRowOffsetsSelected(rows, batch_varbinary_cols_, num_selected,
selection);
RETURN_NOT_OK(rows->AppendEmpty(static_cast<uint32_t>(0),
static_cast<uint32_t>(rows->offsets()[num_selected])));

We first call AppendEmpty to reserve space for x rows but 0 bytes. This is to reserve enough size for the underlying fixed-length buffers: null masks and offsets (for var-length columns).

Then we call GetRowOffsetsSelected to populate the offsets.

At last we call AppendEmpty again with 0 rows but y bytes, where y is the last offset element which is essentially the whole size of the var-length columns.

Sounds all reasonable so far.

However, AppendEmpty calls ResizeOptionalVaryingLengthBuffer, in which:

Status RowTableImpl::ResizeOptionalVaryingLengthBuffer(int64_t num_extra_bytes) {
int64_t num_bytes = offsets()[num_rows_];
if (bytes_capacity_ >= num_bytes + num_extra_bytes || metadata_.is_fixed_length) {
return Status::OK();
}
int64_t bytes_capacity_new = std::max(static_cast<int64_t>(1), 2 * bytes_capacity_);
while (bytes_capacity_new < num_bytes + num_extra_bytes) {
bytes_capacity_new *= 2;
}

We calculate bytes_capacity_new by keeping doubling it until it's big enough for num_bytes + num_extra_bytes.

Note by the time of this point, num_bytes == offsets()[num_rows_] is already y, meanwhile num_extra_bytes is also y, hence the unexpected doubled size than necessary.

What changes are included in this PR?

Fix the wasted half size for buffers in row table. Also add tests to make sure the buffer size is as expected.

Are these changes tested?

UT included.

Are there any user-facing changes?

None.

@zanmato1984 zanmato1984 marked this pull request as draft July 3, 2024 06:25
Copy link

github-actions bot commented Jul 3, 2024

Thanks for opening a pull request!

If this is not a minor PR. Could you open an issue for this pull request on GitHub? https://github.com/apache/arrow/issues/new/choose

Opening GitHub issues ahead of time contributes to the Openness of the Apache Arrow project.

Then could you also rename the pull request title in the following format?

GH-${GITHUB_ISSUE_ID}: [${COMPONENT}] ${SUMMARY}

or

MINOR: [${COMPONENT}] ${SUMMARY}

In the case of PARQUET issues on JIRA the title also supports:

PARQUET-${JIRA_ISSUE_ID}: [${COMPONENT}] ${SUMMARY}

See also:

@zanmato1984
Copy link
Contributor Author

@github-actions crossbow submit -g cpp

@zanmato1984 zanmato1984 force-pushed the fix-row-table-memory-consumption branch from 7b6682c to 342a91d Compare July 3, 2024 06:27
Copy link

github-actions bot commented Jul 3, 2024

Revision: 7b6682c

Submitted crossbow builds: ursacomputing/crossbow @ actions-ea31ebc24b

Task Status
test-alpine-linux-cpp GitHub Actions
test-build-cpp-fuzz GitHub Actions
test-conda-cpp GitHub Actions
test-conda-cpp-valgrind GitHub Actions
test-cuda-cpp GitHub Actions
test-debian-12-cpp-amd64 GitHub Actions
test-debian-12-cpp-i386 GitHub Actions
test-fedora-39-cpp GitHub Actions
test-ubuntu-20.04-cpp GitHub Actions
test-ubuntu-20.04-cpp-bundled GitHub Actions
test-ubuntu-20.04-cpp-minimal-with-formats GitHub Actions
test-ubuntu-20.04-cpp-thread-sanitizer GitHub Actions
test-ubuntu-22.04-cpp GitHub Actions
test-ubuntu-22.04-cpp-20 GitHub Actions
test-ubuntu-22.04-cpp-emscripten GitHub Actions
test-ubuntu-22.04-cpp-no-threading GitHub Actions
test-ubuntu-24.04-cpp GitHub Actions
test-ubuntu-24.04-cpp-gcc-14 GitHub Actions

@zanmato1984
Copy link
Contributor Author

@github-actions crossbow submit -g cpp

Copy link

github-actions bot commented Jul 3, 2024

Revision: 8619d9e

Submitted crossbow builds: ursacomputing/crossbow @ actions-adf44107b5

Task Status
test-alpine-linux-cpp GitHub Actions
test-build-cpp-fuzz GitHub Actions
test-conda-cpp GitHub Actions
test-conda-cpp-valgrind GitHub Actions
test-cuda-cpp GitHub Actions
test-debian-12-cpp-amd64 GitHub Actions
test-debian-12-cpp-i386 GitHub Actions
test-fedora-39-cpp GitHub Actions
test-ubuntu-20.04-cpp GitHub Actions
test-ubuntu-20.04-cpp-bundled GitHub Actions
test-ubuntu-20.04-cpp-minimal-with-formats GitHub Actions
test-ubuntu-20.04-cpp-thread-sanitizer GitHub Actions
test-ubuntu-22.04-cpp GitHub Actions
test-ubuntu-22.04-cpp-20 GitHub Actions
test-ubuntu-22.04-cpp-emscripten GitHub Actions
test-ubuntu-22.04-cpp-no-threading GitHub Actions
test-ubuntu-24.04-cpp GitHub Actions
test-ubuntu-24.04-cpp-gcc-14 GitHub Actions

@zanmato1984
Copy link
Contributor Author

@github-actions crossbow submit -g cpp

Copy link

github-actions bot commented Jul 3, 2024

Revision: daf6d15

Submitted crossbow builds: ursacomputing/crossbow @ actions-29d3b99634

Task Status
test-alpine-linux-cpp GitHub Actions
test-build-cpp-fuzz GitHub Actions
test-conda-cpp GitHub Actions
test-conda-cpp-valgrind GitHub Actions
test-cuda-cpp GitHub Actions
test-debian-12-cpp-amd64 GitHub Actions
test-debian-12-cpp-i386 GitHub Actions
test-fedora-39-cpp GitHub Actions
test-ubuntu-20.04-cpp GitHub Actions
test-ubuntu-20.04-cpp-bundled GitHub Actions
test-ubuntu-20.04-cpp-minimal-with-formats GitHub Actions
test-ubuntu-20.04-cpp-thread-sanitizer GitHub Actions
test-ubuntu-22.04-cpp GitHub Actions
test-ubuntu-22.04-cpp-20 GitHub Actions
test-ubuntu-22.04-cpp-emscripten GitHub Actions
test-ubuntu-22.04-cpp-no-threading GitHub Actions
test-ubuntu-24.04-cpp GitHub Actions
test-ubuntu-24.04-cpp-gcc-14 GitHub Actions

@zanmato1984 zanmato1984 force-pushed the fix-row-table-memory-consumption branch from daf6d15 to b8ff724 Compare July 3, 2024 07:32
@zanmato1984 zanmato1984 changed the title [C++][Compute] Fix the unnecessary extra bytes when encoding row table GH-43129: [C++][Compute] Fix the unnecessary allocation of extra bytes when encoding row table Jul 3, 2024
@zanmato1984 zanmato1984 marked this pull request as ready for review July 3, 2024 15:24
@zanmato1984
Copy link
Contributor Author

Hi @pitrou @westonpace , mind to take a look? This fix reduces the memory footprint of row table almost by half so could be a major improvement. Thanks.


TEST(RowTableMemoryConsumption, Encode) {
constexpr int64_t num_rows_max = 8192;
constexpr int64_t padding_for_vectors = 64;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Refers to this

static constexpr int64_t kPaddingForVectors = 64;

which is always appended to the needed capacity when resizing buffers.

@github-actions github-actions bot added awaiting committer review Awaiting committer review and removed awaiting review Awaiting review labels Jul 3, 2024
Copy link
Member

@pitrou pitrou left a comment

Choose a reason for hiding this comment

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

Sorry for the delay @zanmato1984 !

  1. can you rebase?
  2. please find comments below

@@ -158,8 +158,7 @@ Status RowTableEncoder::EncodeSelected(RowTableImpl* rows, uint32_t num_selected
EncoderOffsets::GetRowOffsetsSelected(rows, batch_varbinary_cols_, num_selected,
selection);

RETURN_NOT_OK(rows->AppendEmpty(static_cast<uint32_t>(0),
static_cast<uint32_t>(rows->offsets()[num_selected])));
RETURN_NOT_OK(rows->AppendEmpty(static_cast<uint32_t>(0), static_cast<uint32_t>(0)));
Copy link
Member

Choose a reason for hiding this comment

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

Can we add parameter names to make sure we understand what's being passed?

Suggested change
RETURN_NOT_OK(rows->AppendEmpty(static_cast<uint32_t>(0), static_cast<uint32_t>(0)));
RETURN_NOT_OK(rows->AppendEmpty(/*xxx=*/ static_cast<uint32_t>(0), /*yyy=*/ static_cast<uint32_t>(0)));

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. Will do.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

int64_t actual_null_mask_size =
num_rows * row_table.metadata().null_masks_bytes_per_row;
ASSERT_GT(actual_null_mask_size * 2,
row_table.buffer_size(0) - padding_for_vectors);
Copy link
Member

Choose a reason for hiding this comment

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

Should we also check that the buffer size is large enough? Same for other inequalities below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, will add them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

} // namespace

TEST(RowTableMemoryConsumption, Encode) {
constexpr int64_t num_rows_max = 8192;
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a comment and GH issue reference to explain what this test is checking for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, will do.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@zanmato1984 zanmato1984 force-pushed the fix-row-table-memory-consumption branch from f202c1a to 185a73c Compare July 9, 2024 16:17
@zanmato1984
Copy link
Contributor Author

Rebase done.

@pitrou pitrou merged commit 3b7ad9d into apache:main Jul 10, 2024
39 checks passed
Copy link

After merging your PR, Conbench analyzed the 4 benchmarking runs that have been run so far on merge-commit 3b7ad9d.

There were no benchmark performance regressions. 🎉

The full Conbench report has more details. It also includes information about 47 possible false positives for unstable benchmarks that are known to sometimes produce them.

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.

2 participants