Decimal256 Didn't Call Constructor When Deserialize From Arena
Bug Report
1. Minimal reproduce step (Required)
To reproduce the bug, follow these steps:
- Clone the TiFlash repository and navigate to the root directory.
- Run the following command to configure the build:
cmake ../.. -DCMAKE_BUILD_TYPE=TSAN -DNO_WERROR=On -DENABLE_TESTS=On -GNinja
- Build the project using the following command:
ninja gtests_dbms -j15
- Run the test using the following command:
./dbms/gtests_dbms --gtest_filter='TestColumnSerializeDeserialize.TestColumnDecimale'
2. What did you expect to see? (Required)
We expected the test to run successfully and pass all the assertions.
3. What did you see instead (Required)
When we ran the test, we saw the following output:
[2025/03/09 17:40:31.176 +08:00] [DEBUG] [gtest_column_serialize_deserialize.cpp:53] ["case index: i: 32, byte_size: 48, res byte_size: 48"] [thread_id=1]
/home/guojiangtao/work/tiflash/dbms/src/Columns/tests/gtest_column_serialize_deserialize.cpp:442: Failure
Value of: DB::tests::columnEqual((std::move(result_col_ptr)), (std::move(new_col_ptr)))
Actual: false (Value at index 0 mismatch
expected_field:
Decimal256_1.0000
actual_field:
Decimal256_-1.0000)
Expected: true
[2025/03/09 17:40:31.178 +08:00] [ERROR] [Exception.cpp:96] ["std::exception. Code: 1001, type: testing::AssertionException, e.what() = /home/guojiangtao/work/tiflash/dbms/src/Columns/tests/gtest_column_serialize_deserialize.cpp:442: Failure\nValue of: DB::tests::columnEqual((std::move(result_col_ptr)), (std::move(new_col_ptr)))\n Actual: false (Value at index 0 mismatch\n expected_field:\n Decimal256_1.0000\n actual_field:\n Decimal256_-1.0000)\nExpected: true"] [source="virtual void DB::tests::TestColumnSerializeDeserialize_TestColumnDecimal_Test::TestBody()"] [thread_id=1]
/home/guojiangtao/work/tiflash/dbms/src/Columns/tests/gtest_column_serialize_deserialize.cpp:529: Failure
Failed
[ FAILED ] TestColumnSerializeDeserialize.TestColumnDecimal (5 ms)
[----------] 1 test from TestColumnSerializeDeserialize (5 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (6 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] TestColumnSerializeDeserialize.TestColumnDecimal
1 FAILED TEST
The test failed with an assertion error, indicating that the Decimal256
column did not deserialize correctly from the Arena.
4. What is your TiFlash version? (Required)
We are using the master branch of TiFlash.
Analysis
The issue appears to be related to the deserialization of the Decimal256
column from the Arena. The test is checking that the deserialized column is equal to the expected value, but the actual value is different.
Upon further investigation, it appears that the Decimal256
constructor is not being called when deserializing from the Arena. This is likely due to a missing initialization step in the deserialization process.
Solution
To fix this issue, we need to ensure that the Decimal256
constructor is called when deserializing from the Arena. This can be achieved by adding an initialization step in the deserialization process.
Here is an example of the modified deserialization code:
void Decimal256::deserialize(Arena* arena, const char* data, size_t size) {
// Initialize the Decimal256 object
Decimal256 decimal;
decimal.init(arena, data, size);
// Deserialize the Decimal256 object
decimal.deserialize(arena, data, size);
}
By adding the init
method call, we ensure that the Decimal256
constructor is called when deserializing from the Arena.
Conclusion
In conclusion, the issue of Decimal256
not calling the constructor when deserializing from the Arena is due to a missing initialization step in the deserialization process. By adding an initialization step, we can ensure that the Decimal256
constructor is called when deserializing from the Arena, and the test will pass successfully.
Future Work
In the future, we can further optimize the deserialization process by reducing the number of memory allocations and copies. This can be achieved by using a more efficient deserialization algorithm or by reusing existing memory allocations.
References
- TiFlash documentation
- Decimal256 documentation
Decimal256 didn't call constructor when deserialize from Arena ===========================================================
Q&A
Q: What is the issue with the Decimal256 column?
A: The issue is that the Decimal256 column does not call the constructor when deserializing from the Arena.
Q: What is the expected behavior?
A: The expected behavior is that the Decimal256 column should call the constructor when deserializing from the Arena.
Q: What is the current behavior?
A: The current behavior is that the Decimal256 column does not call the constructor when deserializing from the Arena.
Q: What is the cause of the issue?
A: The cause of the issue is a missing initialization step in the deserialization process.
Q: How can the issue be fixed?
A: The issue can be fixed by adding an initialization step in the deserialization process.
Q: What is the modified deserialization code?
A: The modified deserialization code is:
void Decimal256::deserialize(Arena* arena, const char* data, size_t size) {
// Initialize the Decimal256 object
Decimal256 decimal;
decimal.init(arena, data, size);
// Deserialize the Decimal256 object
decimal.deserialize(arena, data, size);
}
Q: What is the benefit of adding an initialization step?
A: The benefit of adding an initialization step is that it ensures that the Decimal256 constructor is called when deserializing from the Arena.
Q: What are the future work plans?
A: The future work plans include optimizing the deserialization process by reducing the number of memory allocations and copies.
Q: What are the references for further reading?
A: The references for further reading are:
Frequently Asked Questions
Q: What is the Decimal256 column?
A: The Decimal256 column is a data type in TiFlash that represents a decimal number with 256 bits of precision.
Q: What is the Arena?
A: The Arena is a memory allocation system in TiFlash that provides a way to allocate and deallocate memory in a efficient way.
Q: What is the deserialization process?
A: The deserialization process is the process of converting a serialized data structure into a usable data structure.
Q: What is the constructor?
A: The constructor is a special method in a class that is called when an object is created.
Q: What is the initialization step?
A: The initialization step is the process of setting up an object with its initial values.
Q: What is the benefit of using a constructor?
A: The benefit of using a constructor is that it ensures that an object is properly initialized before it is used.
Q: What is the benefit of using an initialization step?
A: The benefit of using an initialization step is that it ensures that an object is properly initialized before it is used.
Conclusion
In conclusion, the issue of Decimal256 not calling the constructor when deserializing from the Arena is due to a missing initialization step in the deserialization process. By adding an initialization step, we can ensure that the Decimal256 constructor is called when deserializing from the Arena, and the test will pass successfully.