Skip to content

Conversation

@LindaSummer
Copy link
Member

Issue

Close #2791

Proposed Changes

  • implement tdigest.add command.
  • implement tdigest.info command.
  • add integration tests.

Comment

  1. redis tdigest.info has one property Memory usage, and kvrocks's data structure is not in memory, could you give me some suggestions on evaluating the memory usage? 😊
  2. in refactor: hoist key mutexes to ExecuteCommands #2620 , we refactor the lock to outside of the command.
    So, I will remove locks after adding "write" property to commands.
    For quantile command I plan to use "read" property and manually manage the lock to improve performance.

@PragmaTwice PragmaTwice changed the title feat(tdigest): add create and info command. feat(tdigest): add create and info command.\ Feb 21, 2025
@PragmaTwice PragmaTwice changed the title feat(tdigest): add create and info command.\ feat(tdigest): add create and info command Feb 21, 2025
Comment on lines 103 to 105
if (args.size() != 2) {
return {Status::RedisParseErr, kErrWrongNumOfInfoArguments};
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (args.size() != 2) {
return {Status::RedisParseErr, kErrWrongNumOfInfoArguments};
}

Copy link
Member

Choose a reason for hiding this comment

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

This check is redundant.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi @PragmaTwice ,

Got it! I have removed the redundant code. 😊

Best Regards,
Edward

Comment on lines 138 to 139
output->append(redis::BulkString(kInfoMemoryUsage));
output->append(redis::Integer(sizeof(TDigest)));
Copy link
Member

Choose a reason for hiding this comment

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

It seems this is not so useful, and also, not so accurate. Maybe we can just remove this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi @PragmaTwice ,

Thanks for your suggestion! 😊

I have removed this property and left a comment line in code and test case.

Best Regards,
Edward

Comment on lines 59 to 76
bool invalid_keyword = false;
if (args.size() != 2 && (args.size() != 4 || (invalid_keyword = !util::EqualICase(kCompressionArg, args[2])))) {
return {Status::RedisParseErr, invalid_keyword ? kErrWrongKeyword : kErrWrongNumOfCreateArguments};
}
if (parser.EatEqICase(kCompressionArg)) {
auto status = parser.TakeInt<int32_t>();
if (!status) {
return {Status::RedisParseErr, kErrParseCompression};
}
auto compression = *status;
if (compression <= 0) {
return {Status::RedisParseErr, kErrCompressionMustBePositive};
}
if (compression < 1 || compression > static_cast<int32_t>(kTDigestMaxCompression)) {
return {Status::RedisParseErr, kErrCompressionOutOfRange};
}
options_.compression = static_cast<uint32_t>(compression);
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
bool invalid_keyword = false;
if (args.size() != 2 && (args.size() != 4 || (invalid_keyword = !util::EqualICase(kCompressionArg, args[2])))) {
return {Status::RedisParseErr, invalid_keyword ? kErrWrongKeyword : kErrWrongNumOfCreateArguments};
}
if (parser.EatEqICase(kCompressionArg)) {
auto status = parser.TakeInt<int32_t>();
if (!status) {
return {Status::RedisParseErr, kErrParseCompression};
}
auto compression = *status;
if (compression <= 0) {
return {Status::RedisParseErr, kErrCompressionMustBePositive};
}
if (compression < 1 || compression > static_cast<int32_t>(kTDigestMaxCompression)) {
return {Status::RedisParseErr, kErrCompressionOutOfRange};
}
options_.compression = static_cast<uint32_t>(compression);
}
if (parser.EatEqICase(kCompressionArg)) {
auto status = parser.TakeInt<int32_t>();
if (!status) {
return {Status::RedisParseErr, kErrParseCompression};
}
auto compression = *status;
if (compression <= 0) {
return {Status::RedisParseErr, kErrCompressionMustBePositive};
}
if (compression < 1 || compression > static_cast<int32_t>(kTDigestMaxCompression)) {
return {Status::RedisParseErr, kErrCompressionOutOfRange};
}
options_.compression = static_cast<uint32_t>(compression);
}
if (parser.Good()) {
return ... // invalid arguments
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi @PragmaTwice ,

Thanks for your advice! 😊

I have refactored the block with parser.Good().

Best Regards,
Edward

namespace redis {
namespace {
constexpr auto kCompressionArg = "compression";
constexpr auto kErrWrongKeyword = "T-Digest: wrong keyword";
Copy link
Member

Choose a reason for hiding this comment

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

We could remove the prefix(T-Digest) in the error message to be consistent with other commands. Users should know the context according to the command they sent, so that we can avoid creating a dedicated error message for each command.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi @git-hulk ,

Got it! Thanks for your suggestions! 😊

I have removed all T-Digest: prefixes from error message.

Best Regards,
Edward

@LindaSummer LindaSummer force-pushed the feature/tdigest-add-and-info branch from 8b92ed4 to 3622c1d Compare February 22, 2025 03:52

namespace redis {
namespace {
constexpr auto kCompressionArg = "compression";
Copy link
Member

@git-hulk git-hulk Feb 22, 2025

Choose a reason for hiding this comment

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

Could put those error messages into https://github.com/apache/kvrocks/blob/9d2fcdef3bdff9f01451ae72491b3a438b9e6a2f/src/commands/error_constants.h, sorry for forgetting to mention this in the last review. Others are good to me, thanks for your contribution.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi @git-hulk ,

Of course! 😊
I have moved error messages to error_constants.h.

Best Regards,
Edward

Comment on lines 75 to 76
parser.RawTake();
return {Status::RedisParseErr, parser.Good() ? kErrWrongKeyword : kErrWrongNumOfArguments};
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
parser.RawTake();
return {Status::RedisParseErr, parser.Good() ? kErrWrongKeyword : kErrWrongNumOfArguments};
return {Status::RedisParseErr, kErrWrongNumOfArguments};

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi @PragmaTwice ,

Thanks for your suggestion! 😊

I have simplified the logic as suggested.

Best Regards,
Edward

Comment on lines 130 to 141
// require.NoError(t, rdb.Do(ctx, "TDIGEST.CREATE", keyPrefix+"key1", "compression", "1000").Err())
// rsp = rdb.Do(ctx, "TDIGEST.INFO", keyPrefix+"key1")
// require.NoError(t, rsp.Err())
// info = toTdigestInfo(t, rsp.Val())
// require.EqualValues(t, 1000, info.Compression)
// require.EqualValues(t, 1024, info.Capacity) // max is 1024
// require.EqualValues(t, 0, info.MergedNodes)
// require.EqualValues(t, 0, info.UnmergedNodes)
// require.EqualValues(t, 0, info.MergedWeight)
// require.EqualValues(t, 0, info.UnmergedWeight)
// require.EqualValues(t, 0, info.Observations)
// require.EqualValues(t, 0, info.TotalCompressions)
Copy link
Member

Choose a reason for hiding this comment

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

Hmm what's the situation of this commented block?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm what's the situation of this commented block?

Oh, my mistake! Sorry that I think I forgot to recover some parts for debug. I will double check my commit today.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi @PragmaTwice ,

Thanks very much for your correction! ❤

I have recovered the commented test case and have run it in my local environment.

Best Regards,
Edward

@PragmaTwice PragmaTwice changed the title feat(tdigest): add create and info command feat(tdigest): add TDIGEST.CREATE and TDIGEST.INFO command Feb 22, 2025
@PragmaTwice PragmaTwice merged commit 64fbd28 into apache:unstable Feb 22, 2025
35 checks passed
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TDigest: Implement CREATE and INFO command for TDigest Algorithm

3 participants