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

New implementation of getJsonObject #1893

Merged
merged 24 commits into from
Mar 27, 2024
Merged

Conversation

res-life
Copy link
Collaborator

closes #1891

Add a new version of Get json object to replace old version

Signed-off-by: Haoyang Li haoyangl@nvidia.com
Signed-off-by: Chong Gao res_life@163.com

res-life and others added 9 commits March 10, 2024 08:35
* Add Json Parser;
Add Json Parser utility;
Define internal interfaces;
Copy get-json-obj CUDA code from cuDF;

Signed-off-by: Chong Gao <res_life@163.com>

* Code format

---------

Signed-off-by: Chong Gao <res_life@163.com>
Co-authored-by: Chong Gao <res_life@163.com>
Signed-off-by: Chong Gao <res_life@163.com>
Co-authored-by: Chong Gao <res_life@163.com>
…1863)

Signed-off-by: Chong Gao <res_life@163.com>
Co-authored-by: Chong Gao <res_life@163.com>
* Add JNI for GetJsonObject

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

* clean up

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

* Parse json path in plugin

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

* Apply suggestions from code review

Co-authored-by: Nghia Truong <7416935+ttnghia@users.noreply.github.com>

* Use table_view

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

* Update java

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

* Apply suggestions from code review

Co-authored-by: Nghia Truong <7416935+ttnghia@users.noreply.github.com>

* clean up

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

* use matched enum for type

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

* clean up

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

* upmerge

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

* format

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

---------

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>
Co-authored-by: Nghia Truong <7416935+ttnghia@users.noreply.github.com>
Signed-off-by: Chong Gao <res_life@163.com>
Co-authored-by: Chong Gao <res_life@163.com>
* Optimize match_current_field_name using less memory

Signed-off-by: Chong Gao <res_life@163.com>

* Convert a function to device code

* Add a JNI test case

* Add JNI test case

* Change nesting depth to 4

* Change nesting depth to 8 to fix test

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

* remove clang format change

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

---------

Signed-off-by: Chong Gao <res_life@163.com>
Signed-off-by: Haoyang Li <haoyangl@nvidia.com>
Co-authored-by: Chong Gao <res_life@163.com>
* Change recursive to iterative

Signed-off-by: Chong Gao <res_life@163.com>

---------

Signed-off-by: Chong Gao <res_life@163.com>
Co-authored-by: Chong Gao <res_life@163.com>
@res-life
Copy link
Collaborator Author

build

@res-life
Copy link
Collaborator Author

@ttnghia Help review

@res-life
Copy link
Collaborator Author

build

@res-life res-life changed the title Get json object: merge branch feature to release branch Get json object: merge feature branch to release branch Mar 25, 2024
@res-life
Copy link
Collaborator Author

build

@res-life res-life requested review from ttnghia and revans2 March 25, 2024 11:54

extern "C" {
JNIEXPORT jlong JNICALL Java_com_nvidia_spark_rapids_jni_JSONUtils_getJsonObject(
JNIEnv* env, jclass, jlong input_column, jint size, jobjectArray path_instructions)
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: why do we need size if the path_instructions is an array that stores the size in it?

Copy link
Collaborator

Choose a reason for hiding this comment

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

done.

for (int i = 0; i < size; i++) {
jobject instruction = env->GetObjectArrayElement(path_instructions, i);
JNI_NULL_CHECK(env, instruction, "path_instruction is null", 0);
jclass instruction_class = env->GetObjectClass(instruction);
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: can we have a follow on where we change this to be 3 arrays? one that is an int array for the type, another that is a string array, and the last one would be a long array? This would reduce the number of reflection calls that would need to be done. This is very minor.

Copy link
Collaborator

@ttnghia ttnghia Mar 25, 2024

Choose a reason for hiding this comment

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

Humnn, probably I was the one that asked for using array of structs instead of individual arrays. But yeah for data transfer from Java to C++ then individual arrays seem to be better. I'm sorry @res-life.

Edit: I have a better idea. We want to have array of structs because that is simpler to iterate through the instructions. With individual arrays, we still can use thrust::zip_iterator to zip together multiple arrays with just one iterator and iterate through them easily. Of course this is not required to be in this PR but future work.

Copy link
Collaborator

Choose a reason for hiding this comment

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

thrust::zip_iterator looks good, will do in a follow-on

@Test
void getJsonObjectTest() {
JSONUtils.PathInstructionJni[] query = new JSONUtils.PathInstructionJni[2];
query[0] = new JSONUtils.PathInstructionJni(JSONUtils.PathInstructionType.KEY, "", -1);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we support arrays yet? I don't see any tests that include an array index that is not -1.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added a case to query $[1][2]

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

}

public enum PathInstructionType {
SUBSCRIPT,
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: I would prefer to have the enum to int mapping be specific instead of using the ordinal. It is minor, but helps to prevent issues where one is updated and the other is missed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

will do in a follow-on

NAMED
}

public static class PathInstructionJni {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we have some javadocs on this, and the constructor. It is not always clear what it does.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

will do in a follow-on

}
}

public static ColumnVector getJsonObject(ColumnVector input, int size, PathInstructionJni[] path_instructions) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Again not sure why size is needed here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

done.

Copy link
Collaborator

@ttnghia ttnghia left a comment

Choose a reason for hiding this comment

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

Flush my first round of review for quick response while continuing the review process. Overall, I don't find any big concerns since we are currently prioritizing correctness over clean code. But definitely we need to have follow up work with a lot of things to do.

namespace spark_rapids_jni {

namespace detail {
// namespace {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: left over for removal. Or it should be uncommented.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done, removed.

Comment on lines 96 to 103
__device__ bool evaluate_path(json_parser<>& p,
json_generator<>& g,
write_style style,
path_instruction const* path_ptr,
int path_size)
{
return path_evaluator::evaluate_path(p, g, style, path_ptr, path_size);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh this is just calling to another function. Why do we ever need it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done, removed.

src/main/cpp/src/get_json_object.cu Outdated Show resolved Hide resolved
Comment on lines 133 to 136
* @param commands The command buffer to be applied to the string. Always ends
* with a path_operator_type::END
* @param out_buf Buffer user to store the results of the query (nullptr in the
* size computation step)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: This is better for readability.

Suggested change
* @param commands The command buffer to be applied to the string. Always ends
* with a path_operator_type::END
* @param out_buf Buffer user to store the results of the query (nullptr in the
* size computation step)
* @param commands The command buffer to be applied to the string. Always ends
* with a path_operator_type::END
* @param out_buf Buffer user to store the results of the query (nullptr in the
* size computation step)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Comment on lines 183 to 185
* This kernel operates in a 2-pass way. On the first pass, it computes
* output sizes. On the second pass it fills in the provided output buffers
* (chars and validity)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
* This kernel operates in a 2-pass way. On the first pass, it computes
* output sizes. On the second pass it fills in the provided output buffers
* (chars and validity)
* This kernel operates in a 2-pass way. On the first pass it computes the
* output sizes. On the second pass, it fills in the provided output buffers
* (chars and validity).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Comment on lines 713 to 726
CUDF_HOST_DEVICE context& operator=(const context& other)
{
token = other.token;
case_path = other.case_path;
g = other.g;
style = other.style;
path_ptr = other.path_ptr;
path_size = other.path_size;
task_is_done = other.task_is_done;
dirty = other.dirty;
is_first_enter = other.is_first_enter;
child_g = other.child_g;

return *this;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This seems to have nothing special, so just leave the compiler do it.

Suggested change
CUDF_HOST_DEVICE context& operator=(const context& other)
{
token = other.token;
case_path = other.case_path;
g = other.g;
style = other.style;
path_ptr = other.path_ptr;
path_size = other.path_size;
task_is_done = other.task_is_done;
dirty = other.dirty;
is_first_enter = other.is_first_enter;
child_g = other.child_g;
return *this;
CUDF_HOST_DEVICE context& operator=(context const&) = default;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

* input json string is invalid.
*/
std::unique_ptr<cudf::column> get_json_object(
cudf::strings_column_view const& col,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
cudf::strings_column_view const& col,
cudf::strings_column_view const& input,

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Comment on lines +175 to +180
template <bool allow_single_quotes = curr_allow_single_quotes,
bool allow_unescaped_control_chars = curr_allow_unescaped_control_chars,
int max_json_nesting_depth = curr_max_json_nesting_depth,
int max_string_utf8_bytes = curr_max_string_utf8_bytes,
int max_num_len = curr_max_num_len,
bool allow_tailing_sub_string = curr_allow_tailing_sub_string>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: Oh no, too many template parameters. They will make compilation very slow. We should better use run time parameters, except only the parameters that need to be known at compile time. In future work we have to clean up this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Only have one template combination.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will do in a follow-on.

Comment on lines +26 to +28
/**
* write style when writing out JSON string
*/
Copy link
Collaborator

Choose a reason for hiding this comment

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

My comment for the docs in this file is similar to the previous one: Don't use non-standard oxygen. I'm fine to leave them for now but we have to cleanup in the follow up work.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will do in a follow-on.

/**
* is current position EOF
*/
CUDF_HOST_DEVICE inline bool eof(char const* pos) { return pos >= json_end_pos; }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also CUDF_HOST_DEVICEs need to be only __device__ if possible.

Copy link
Collaborator

Choose a reason for hiding this comment

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

done.

@res-life
Copy link
Collaborator Author

Flush my first round of review for quick response while continuing the review process. Overall, I don't find any big concerns since we are currently prioritizing correctness over clean code. But definitely we need to have follow up work with a lot of things to do.

Yes, follow up things:

  • Performance tuning/improvement.
  • Convert test cases on CPU to GPU.

@res-life
Copy link
Collaborator Author

build


String JSON = "[100.0,200.000,351.980]";
String expectedStr = "[100.0,200.000,351.980]";
try (
Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems it is a temp test data?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

updated.

* Support number normalization

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

* delete cpp test and add a java test case

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>

---------

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>
/**
* write JSON style
*/
enum class write_style { raw_style, quoted_style, flatten_style };
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: Enum class values should be ALL_CAP. In addition, they don't have to all have the suffix _style.

Suggested change
enum class write_style { raw_style, quoted_style, flatten_style };
enum class write_style { RAW, QUOTED, FLATTEN };

Copy link
Collaborator

Choose a reason for hiding this comment

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

BTW, why path_instruction_type is outside while write_style is inside namespace detail?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

src/main/cpp/src/JSONUtilsJni.cpp refers to it.

case 't':
if (nullptr != copy_dest && write_style::unescaped == w_style) { *copy_dest++ = '\t'; }
if (copy_dest != nullptr && write_style::escaped == w_style) {
if (copy_dest != nullptr) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Check again: copy_dest != nullptr, it is redudant.
Go through all copy_dest and w_style related paths.
And add cases.

@mythrocks
Copy link
Collaborator

Could we consider changing the title of this PR? Perhaps "New implementation of getJsonObject", or something more descriptive?

bool scientificNotation = (exp < -3) || (exp >= 7);

// Values in the interval [1E-3, 1E7) are special.
if (scientificNotation) {
// Print in the format x.xxxxxE-yy.
for (uint32_t i = 0; i < olength - 1; ++i) {
uint32_t const c = output % 10;
for (int i = 0; i < olength - 1; ++i) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not necessary to change this, but we could have gotten away with the following:

Suggested change
for (int i = 0; i < olength - 1; ++i) {
for (auto i = 0; i < olength - 1; ++i) {

Copy link
Collaborator

Choose a reason for hiding this comment

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

Alternatively, let's use int32_t consistently. No need to bring int into it also.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will do in a follow-on.

@res-life res-life changed the title Get json object: merge feature branch to release branch New implementation of getJsonObject Mar 26, 2024
@res-life
Copy link
Collaborator Author

Could we consider changing the title of this PR? Perhaps "New implementation of getJsonObject", or something more descriptive?

Done.

// no NaN in json
if (exponent) {
if (sign) {
memcpy(result, "\"-Infinity\"", 11);
Copy link
Collaborator

@mythrocks mythrocks Mar 26, 2024

Choose a reason for hiding this comment

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

Nitpick: Feel free to ignore:

I had to count the characters to make sure 11 is right. :]
One trick is to use sizeof("\"-Infinity\"") - 1. That is constexpr and should yield 11.
I suspect strlen("\"-Infinity\"") is more readable, but I'm not sure it's constexpr in __device__. (I know it is in __host__ C++.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will do in a follow-on.

@@ -1424,4 +1475,15 @@ __device__ inline int format_float(double value, int digits, bool is_float, char
}
}

//===== json_parser utility =====

__device__ inline int double_normalization(double value, char* output)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's consider renaming this to normalize_double().
Also, consider a function doc line indicating the protocol of returning the number of characters if output is nullptr.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will do in a follow-on.

: output(nullptr), output_len(0), hide_outer_array_tokens(_hide_outer_array_tokens)
{
}
__device__ json_generator<>& operator=(const json_generator<>& other)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
__device__ json_generator<>& operator=(const json_generator<>& other)
__device__ json_generator<>& operator=(json_generator<> const& other)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

/**
* write JSON style
*/
enum class write_style { raw_style, quoted_style, flatten_style };
Copy link
Collaborator

Choose a reason for hiding this comment

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

BTW, why path_instruction_type is outside while write_style is inside namespace detail?

/**
* path evaluator which can run on both CPU and GPU
*/
struct path_evaluator {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: Device code and/or class with device code should be placed in .cu or .cuh files. .hpp files should never contain device code.

constexpr int max_path_depth = 32;

// stack
context stack[max_path_depth];
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure about this declaration but feel really nervous about it. Typically, a GPU thread has very limited resources (memory/registers etc). Reserving a large array in a thread will stress on the resources, which results in fewer number of threads per block and reduces performance. Probably the better way is to declare this as a shared memory array instead. I'm not 100% sure until we can run profiling on this.

Copy link
Collaborator

Choose a reason for hiding this comment

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

In addition, the code below also has a lot of if/else branches without any thread sync. Thus, thread divergence may occur which causes further slowdown. I have little idea about what can we improve for that huge while loop 😢

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I filed a following on perf issue:
#1907

Comment on lines +32 to +39
enum class write_style {
// e.g.: '\\r' is a string with 2 chars '\' 'r', writes 1 char '\r'
unescaped,

// * e.g.: '"' is a string with 1 char '"', writes out 4 chars '"' '\' '\"'
// '"'
escaped
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
enum class write_style {
// e.g.: '\\r' is a string with 2 chars '\' 'r', writes 1 char '\r'
unescaped,
// * e.g.: '"' is a string with 1 char '"', writes out 4 chars '"' '\' '\"'
// '"'
escaped
};
enum class write_style {
// e.g.: '\\r' is a string with 2 chars '\' 'r', writes 1 char '\r'
UNESCAPED,
// * e.g.: '"' is a string with 1 char '"', writes out 4 chars '"' '\' '\"'
// '"'
ESCAPED
};

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will fix in a follow-on

Comment on lines +184 to +192
class json_parser {
public:
__device__ inline json_parser(char const* const _json_start_pos, cudf::size_type const _json_len)
: json_start_pos(_json_start_pos),
json_end_pos(_json_start_pos + _json_len),
curr_pos(_json_start_pos)
{
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Again, device code should be in .cuh file.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will fix in a follow-on


__device__ inline int double_normalization(double value, char* output)
{
if (output == nullptr) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I haven't fully grasped the control flow, so this might be a silly observation:

We might be inadvertently checking output == nullptr multiple times, both from the call-site and here. Since this is a __device__ function, this might amount to a lot of calls.

In a follow-up, there might be value in separating those call chains. Computing the sizes can be done separately from actually writing the normalized value. Just a thought for future consideration.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Will fix in a follow-on

auto const& [type, name, index] = inst;
switch (type) {
case path_instruction_type::SUBSCRIPT:
path_commands.emplace_back(path_instruction{path_instruction_type::SUBSCRIPT});
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nitpick: If we're using emplace_back, we might be able to get away with:

Suggested change
path_commands.emplace_back(path_instruction{path_instruction_type::SUBSCRIPT});
path_commands.emplace_back(path_instruction_type::SUBSCRIPT);

@res-life
Copy link
Collaborator Author

build

Signed-off-by: Haoyang Li <haoyangl@nvidia.com>
@res-life
Copy link
Collaborator Author

For further verification, please run compute-sanitizer with Java test to make sure we don't have memory bug (using the tutorial for standalone mode in https://nvidia.github.io/spark-rapids/docs/dev/compute_sanitizer.html).

Done for the JNI case: GetJsonObjectTest.java

@res-life
Copy link
Collaborator Author

build

@res-life
Copy link
Collaborator Author

res-life commented Mar 27, 2024

Filed 3 follow-on issues:
Doc follow-on: #1905
Comments follow-on: #1906
Perf follow-on: #1907

@res-life
Copy link
Collaborator Author

Now the GetJsonObjectTest.java already tested all the case paths of evaluate_path.
And Spark-Rapids PR also verified the issues:

Fixes #10218
Fixes #10212
Fixes #10194
Fixes #10196
Fixes #10537
Fixes #10216
Fixes #10217
Fixes #9033

@ttnghia I think it's safe to merge this PR now.

@res-life
Copy link
Collaborator Author

build

@res-life
Copy link
Collaborator Author

res-life commented Mar 27, 2024

Sorry, one more fix.
Please allow me to say it again: I think it's safe to merge this PR now.
Locally, I got a 100% code coverage for JSON generator and evaluate_path.

@ttnghia
Copy link
Collaborator

ttnghia commented Mar 27, 2024

I think it's safe to merge this PR now.

Is there any chance to run compute-sanitizer on the tests before merging?

@thirtiseven
Copy link
Collaborator

I think it's safe to merge this PR now.

Is there any chance to run compute-sanitizer on the tests before merging?

Tests can pass with sanitizer on.

Merging it…

@thirtiseven thirtiseven merged commit 87216f2 into branch-24.04 Mar 27, 2024
3 checks passed
@res-life res-life deleted the get-json-object-feature branch March 27, 2024 15:48
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.

GetJsonObject: Merge feature branch to release branch
5 participants