-
Notifications
You must be signed in to change notification settings - Fork 553
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
base: main
Are you sure you want to change the base?
Changes from all commits
2463f3a
71617ee
c3b0ad1
7b534a6
7650f5f
6c9c347
50633a0
e2eaa0a
dce580f
005e98d
0265708
ebb4f25
46d27b3
84c0aca
02b6077
a32bd7e
919e2b4
bc6483d
a12baba
23d4ca3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
"$.store.book[0].title", | ||
"$.store.book[*].author", | ||
"$.store.book[?(@.price < 10)].title", | ||
"$.store.bicycle.color", | ||
"$.store.book[*]", // all books | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: indents are wonky, just replace with a single space |
||
"$.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); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// 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 | ||
{ | ||
// Existing commands | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Existing & new with regards to what? These would all be existing commands once the PR is merged... |
||
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; | ||
|
||
// New commands for different JsonPath patterns | ||
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; | ||
|
||
private static string GenerateLargeJson(int items) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Please place the private methods after the public ones |
||
{ | ||
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 NoOpModule.NoOpModule(), [], out _); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is the No-op module needed here? |
||
server.Register.NewModule(new GarnetJSON.Module(), [], out _); | ||
} | ||
|
||
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); | ||
} | ||
} | ||
} |
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.
This looks weird, should this be here?