-
Notifications
You must be signed in to change notification settings - Fork 557
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
JSON Module rewrite with custom JSONPath implementation #974
Open
Vijay-Nirmal
wants to merge
23
commits into
microsoft:main
Choose a base branch
from
Vijay-Nirmal:new/json-module-rewrite
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+6,644
−414
Open
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
2463f3a
Initial commit of Json Module rewrite
Vijay-Nirmal 71617ee
Changed Test to use JsonNode directly
Vijay-Nirmal c3b0ad1
Implementation of JSON.GET and SET commands
Vijay-Nirmal 7b534a6
Moved other moduels from Json BDN
Vijay-Nirmal 7650f5f
Added more benchmark
Vijay-Nirmal 6c9c347
Moved json modulke to root location
Vijay-Nirmal 50633a0
Updated Licenses
Vijay-Nirmal e2eaa0a
Added documentation
Vijay-Nirmal dce580f
Code cleanup and code comments
Vijay-Nirmal 005e98d
Merge branch 'main' into new/json-module-rewrite
Vijay-Nirmal 0265708
Fixed code format
Vijay-Nirmal ebb4f25
Fixed build issue
Vijay-Nirmal 46d27b3
Added more test cases
Vijay-Nirmal 84c0aca
Added more test cases
Vijay-Nirmal 02b6077
Fix formating
Vijay-Nirmal a32bd7e
Merged latest
Vijay-Nirmal 919e2b4
Add expected values for ACL and AOF operations in benchmark config
Vijay-Nirmal bc6483d
Merge branch 'main' into new/json-module-rewrite
Vijay-Nirmal a12baba
Fixed test case failure
Vijay-Nirmal 23d4ca3
Merge branch 'main' into new/json-module-rewrite
Vijay-Nirmal 9f437c3
Merged latest
Vijay-Nirmal 4207c8d
Review comment fixes
Vijay-Nirmal 243b136
Fxied format issue
Vijay-Nirmal File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using System.Text.Json.Nodes; | ||
using BenchmarkDotNet.Attributes; | ||
using BenchmarkDotNet.Engines; | ||
using GarnetJSON.JSONPath; | ||
|
||
namespace BDN.benchmark.Json; | ||
|
||
[MemoryDiagnoser] | ||
public class JsonPathQuery | ||
{ | ||
private JsonNode _jsonNode; | ||
|
||
private readonly Consumer _consumer = new Consumer(); | ||
|
||
[Params( | ||
"$.store.book[0].title", | ||
"$.store.book[*].author", | ||
"$.store.book[?(@.price < 10)].title", | ||
"$.store.bicycle.color", | ||
"$.store.book[*]", // all books | ||
"$.store..price", // all prices using recursive descent | ||
"$..author", // all authors using recursive descent | ||
"$.store.book[?(@.price > 10 && @.price < 20)]", // filtered by price range | ||
"$.store.book[?(@.category == 'fiction')]", // filtered by category | ||
"$.store.book[-1:]", // last book | ||
"$.store.book[:2]", // first two books | ||
"$.store.book[?(@.author =~ /.*Waugh/)]", // regex match on author | ||
"$..book[0,1]", // union of array indices | ||
"$..*", // recursive descent all nodes | ||
"$..['bicycle','price']", // recursive descent specfic node with name match | ||
"$..[?(@.price < 10)]", // recursive descent specfic node with conditionally match | ||
"$.store.book[?(@.author && @.title)]", // existence check | ||
"$.store.*" // wildcard child | ||
)] | ||
public string JsonPath { get; set; } | ||
|
||
[GlobalSetup] | ||
public void Setup() | ||
{ | ||
var jsonString = """ | ||
{ | ||
"store": { | ||
"book": [ | ||
{ | ||
"category": "reference", | ||
"author": "Nigel Rees", | ||
"title": "Sayings of the Century", | ||
"price": 8.95 | ||
}, | ||
{ | ||
"category": "fiction", | ||
"author": "Evelyn Waugh", | ||
"title": "Sword of Honour", | ||
"price": 12.99 | ||
} | ||
], | ||
"bicycle": { | ||
"color": "red", | ||
"price": 19.95 | ||
} | ||
} | ||
} | ||
"""; | ||
|
||
_jsonNode = JsonNode.Parse(jsonString); | ||
} | ||
|
||
[Benchmark] | ||
public void SelectNodes() | ||
{ | ||
var result = _jsonNode.SelectNodes(JsonPath); | ||
result.Consume(_consumer); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT license. | ||
|
||
using System.Text; | ||
using BenchmarkDotNet.Attributes; | ||
using Embedded.server; | ||
|
||
namespace BDN.benchmark.Operations | ||
{ | ||
/// <summary> | ||
/// Benchmark for ModuleOperations | ||
/// </summary> | ||
[MemoryDiagnoser] | ||
public class JsonOperations : OperationsBase | ||
{ | ||
static ReadOnlySpan<byte> JSONGETCMD => "*3\r\n$8\r\nJSON.GET\r\n$2\r\nk3\r\n$1\r\n$\r\n"u8; | ||
static ReadOnlySpan<byte> JSONSETCMD => "*4\r\n$8\r\nJSON.SET\r\n$2\r\nk3\r\n$4\r\n$.f2\r\n$1\r\n2\r\n"u8; | ||
static ReadOnlySpan<byte> JSONGET_DEEP => "*3\r\n$8\r\nJSON.GET\r\n$4\r\nbig1\r\n$12\r\n$.data[0].id\r\n"u8; | ||
static ReadOnlySpan<byte> JSONGET_ARRAY => "*3\r\n$8\r\nJSON.GET\r\n$4\r\nbig1\r\n$13\r\n$.data[*]\r\n"u8; | ||
static ReadOnlySpan<byte> JSONGET_ARRAY_ELEMENTS => "*3\r\n$8\r\nJSON.GET\r\n$4\r\nbig1\r\n$13\r\n$.data[*].id\r\n"u8; | ||
static ReadOnlySpan<byte> JSONGET_FILTER => "*3\r\n$8\r\nJSON.GET\r\n$4\r\nbig1\r\n$29\r\n$.data[?(@.active==true)]\r\n"u8; | ||
static ReadOnlySpan<byte> JSONGET_RECURSIVE => "*3\r\n$8\r\nJSON.GET\r\n$4\r\nbig1\r\n$4\r\n$..*\r\n"u8; | ||
|
||
Request jsonGetCmd; | ||
Request jsonSetCmd; | ||
Request jsonGetDeepCmd; | ||
Request jsonGetArrayCmd; | ||
Request jsonGetArrayElementsCmd; | ||
Request jsonGetFilterCmd; | ||
Request jsonGetRecursiveCmd; | ||
|
||
public override void GlobalSetup() | ||
{ | ||
base.GlobalSetup(); | ||
RegisterModules(); | ||
|
||
SetupOperation(ref jsonGetCmd, JSONGETCMD); | ||
SetupOperation(ref jsonSetCmd, JSONSETCMD); | ||
SetupOperation(ref jsonGetDeepCmd, JSONGET_DEEP); | ||
SetupOperation(ref jsonGetArrayCmd, JSONGET_ARRAY); | ||
SetupOperation(ref jsonGetArrayElementsCmd, JSONGET_ARRAY_ELEMENTS); | ||
SetupOperation(ref jsonGetFilterCmd, JSONGET_FILTER); | ||
SetupOperation(ref jsonGetRecursiveCmd, JSONGET_RECURSIVE); | ||
|
||
// Setup test data | ||
var largeJson = GenerateLargeJson(20); | ||
SlowConsumeMessage(Encoding.UTF8.GetBytes($"*4\r\n$8\r\nJSON.SET\r\n$4\r\nbig1\r\n$1\r\n$\r\n${largeJson.Length}\r\n{largeJson}\r\n")); | ||
|
||
// Existing setup | ||
SlowConsumeMessage("*4\r\n$8\r\nJSON.SET\r\n$2\r\nk3\r\n$1\r\n$\r\n$14\r\n{\"f1\":{\"a\":1}}\r\n"u8); | ||
SlowConsumeMessage(JSONGETCMD); | ||
SlowConsumeMessage(JSONSETCMD); | ||
} | ||
|
||
[Benchmark] | ||
public void ModuleJsonGetCommand() | ||
{ | ||
Send(jsonGetCmd); | ||
} | ||
|
||
[Benchmark] | ||
public void ModuleJsonSetCommand() | ||
{ | ||
Send(jsonSetCmd); | ||
} | ||
|
||
[Benchmark] | ||
public void ModuleJsonGetDeepPath() | ||
{ | ||
Send(jsonGetDeepCmd); | ||
} | ||
|
||
[Benchmark] | ||
public void ModuleJsonGetArrayPath() | ||
{ | ||
Send(jsonGetArrayCmd); | ||
} | ||
|
||
[Benchmark] | ||
public void ModuleJsonGetArrayElementsPath() | ||
{ | ||
Send(jsonGetArrayElementsCmd); | ||
} | ||
|
||
[Benchmark] | ||
public void ModuleJsonGetFilterPath() | ||
{ | ||
Send(jsonGetFilterCmd); | ||
} | ||
|
||
[Benchmark] | ||
public void ModuleJsonGetRecursive() | ||
{ | ||
Send(jsonGetRecursiveCmd); | ||
} | ||
|
||
private static string GenerateLargeJson(int items) | ||
{ | ||
var data = new StringBuilder(); | ||
data.Append("{\"data\":["); | ||
|
||
for (int i = 0; i < items; i++) | ||
{ | ||
if (i > 0) data.Append(','); | ||
data.Append($$""" | ||
{ | ||
"id": {{i}}, | ||
"name": "Item{{i}}", | ||
"active": {{(i % 2 == 0).ToString().ToLower()}}, | ||
"value": {{i * 100}}, | ||
"nested": { | ||
"level1": { | ||
"level2": { | ||
"value": {{i}} | ||
} | ||
} | ||
} | ||
} | ||
"""); | ||
} | ||
|
||
data.Append("]}"); | ||
return data.ToString(); | ||
} | ||
|
||
private void RegisterModules() | ||
{ | ||
server.Register.NewModule(new GarnetJSON.Module(), [], out _); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General Q - where did these test cases come from? Just curious if this is copied from somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have asked Copilot to create sample JPaths for each type of JPath supported by Redis and Newtonsoft