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

Perf work on Patch models - WIP #9

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion eng/Packages.Data.props
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@
All should have PrivateAssets="All" set so they don't become package dependencies
-->
<ItemGroup>
<PackageReference Update="Microsoft.Azure.AutoRest.CSharp" Version="3.0.0-beta.20230815.1" PrivateAssets="All" />
<PackageReference Update="Microsoft.Azure.AutoRest.CSharp" Version="3.0.0-beta.20230817.1" PrivateAssets="All" />
<PackageReference Update="Azure.ClientSdk.Analyzers" Version="0.1.1-dev.20230811.4" PrivateAssets="All" />
<PackageReference Update="coverlet.collector" Version="3.2.0" PrivateAssets="All" />
<PackageReference Update="Microsoft.CodeAnalysis.NetAnalyzers" Version="7.0.1" PrivateAssets="All" />
Expand Down
2 changes: 1 addition & 1 deletion eng/emitter-package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"main": "dist/src/index.js",
"dependencies": {
"@azure-tools/typespec-csharp": "0.2.0-beta.20230815.1"
"@azure-tools/typespec-csharp": "0.2.0-beta.20230817.1"
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Release History

## 1.2.0-beta.1 (Unreleased)
## 1.2.0 (2023-08-03)

### Bugs Fixed

- Service calls that result in a `HttpStatusCode.NotFound` status will now be retried by default. This is to handle scenarios where there is an unexpected loss of session stickiness when the connected node changes and transactions have not been fully replicated.

## 1.2.0-beta.1 (2022-11-09)

### Features Added

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "net",
"TagPrefix": "net/confidentialledger/Azure.Security.ConfidentialLedger",
"Tag": "net/confidentialledger/Azure.Security.ConfidentialLedger_48488df791"
"Tag": "net/confidentialledger/Azure.Security.ConfidentialLedger_5657482b45"
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<Description>Client SDK for the Azure Confidential Ledger service</Description>
<AssemblyTitle>Azure Confidential Ledger</AssemblyTitle>
<Version>1.2.0-beta.1</Version>
<Version>1.2.0</Version>
<!--The ApiCompatVersion is managed automatically and should not generally be modified manually.-->
<ApiCompatVersion>1.1.0</ApiCompatVersion>
<PackageTags>Azure ConfidentialLedger</PackageTags>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,19 @@ internal ConfidentialLedgerClient(Uri ledgerEndpoint, TokenCredential credential
Array.Empty<HttpPipelinePolicy>() :
new HttpPipelinePolicy[] { new BearerTokenAuthenticationPolicy(_tokenCredential, AuthorizationScopes) },
transportOptions,
new ResponseClassifier());
new ConfidentialLedgerResponseClassifier());
_ledgerEndpoint = ledgerEndpoint;
_apiVersion = actualOptions.Version;
}

internal class ConfidentialLedgerResponseClassifier : ResponseClassifier
{
public override bool IsRetriableResponse(HttpMessage message)
{
return base.IsRetriableResponse(message) || message.Response.Status == 404;
}
}

/// <summary> Posts a new entry to the ledger. A collection id may optionally be specified. </summary>
/// <remarks>
/// Below is the JSON schema for the request and response payloads.
Expand Down
30 changes: 29 additions & 1 deletion sdk/core/Azure.Core/perf/Serializations/JsonBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,23 @@ public void Serialize_PublicInterface()

[Benchmark]
[BenchmarkCategory("Internal")]
public T Deserialize_Internal()
public T Deserialize_Internal_JsonElement()
{
return Deserialize(_jsonDocument.RootElement);
}

protected virtual T Deserialize(BinaryData data)
{
return Deserialize(JsonDocument.Parse(data).RootElement);
}

[Benchmark]
[BenchmarkCategory("Internal")]
public T Deserialize_Internal_BinaryData()
{
return Deserialize(_data);
}

[Benchmark]
[BenchmarkCategory("Cast")]
public T Deserialize_ExplicitCast()
Expand Down Expand Up @@ -189,5 +201,21 @@ public void JsonDocumentFromBinaryData()
{
using var doc = JsonDocument.Parse(_data);
}

protected virtual void ModifyValues(T model) { }

[Benchmark]
[BenchmarkCategory("Usage")]
public void EndToEndUseCase()
{
// Instantiate an input model
T model = ModelSerializer.Deserialize<T>(_data);

// Set properties on it
ModifyValues(model);

// Send it over the wire - serialize
RequestContent content = CastToRequestContent();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.IO;
using System.Text.Json;
using Azure.Core.Tests.PatchModels;

namespace Azure.Core.Perf.Serializations
{
public class SimplePatchModelBenchmark : JsonBenchmark<SimplePatchModel>
{
protected override SimplePatchModel CastFromResponse() => (SimplePatchModel)_response;

protected override RequestContent CastToRequestContent() => _model;

protected override SimplePatchModel Deserialize(JsonElement jsonElement)
{
using Stream stream = new MemoryStream();
using Utf8JsonWriter writer = new(stream);
jsonElement.WriteTo(writer);
writer.Flush();
stream.Position = 0;
return Deserialize(BinaryData.FromStream(stream));
}

protected override SimplePatchModel Deserialize(BinaryData data) => SimplePatchModel.Deserialize(data);

protected override void Serialize(Utf8JsonWriter writer) => _model.Serialize(writer);

protected override string JsonFileName => "SimplePatchModel.json";

protected override void ModifyValues(SimplePatchModel model)
{
model.Name = "xyz";
model.Count = 2;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Text.Json;
using Azure.Core.Tests.PatchModels;

namespace Azure.Core.Perf.Serializations
{
public class SimpleStandardModelBenchmark : JsonBenchmark<SimpleStandardModel>
{
protected override SimpleStandardModel CastFromResponse() => (SimpleStandardModel)_response;

protected override RequestContent CastToRequestContent() => _model;

protected override SimpleStandardModel Deserialize(JsonElement jsonElement)
{
return SimpleStandardModel.DeserializeSimpleStandardModel(jsonElement, new("J"));
}

protected override void Serialize(Utf8JsonWriter writer) => _model.Serialize(writer);

protected override string JsonFileName => "SimplePatchModel.json";

protected override void ModifyValues(SimpleStandardModel model)
{
model.Name = "xyz";
model.Count = 2;
}
}
}
145 changes: 136 additions & 9 deletions sdk/core/Azure.Core/src/DynamicData/DynamicData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,12 @@ private IEnumerable GetEnumerable()
if (_options.PropertyNameFormat == JsonPropertyNames.UseExact ||
_element.TryGetProperty(name, out MutableJsonElement _))
{
_element = _element.SetProperty(name, value);
SetPropertyInternal(name, value);
return null;
}

// The dynamic content has a specified property name format.
_element = _element.SetProperty(FormatPropertyName(name), value);
SetPropertyInternal(FormatPropertyName(name), value);

// Binding machinery expects the call site signature to return an object
return null;
Expand All @@ -166,11 +166,8 @@ private IEnumerable GetEnumerable()
_ => false
};

private object ConvertType(object value)
{
byte[] bytes = JsonSerializer.SerializeToUtf8Bytes(value, _serializerOptions);
return JsonDocument.Parse(bytes);
}
private JsonElement ConvertType(object value) =>
MutableJsonElement.SerializeToJsonElement(value, _serializerOptions);

private object? SetViaIndexer(object index, object value)
{
Expand All @@ -179,17 +176,147 @@ private object ConvertType(object value)
switch (index)
{
case string propertyName:
_element = _element.SetProperty(propertyName, value);
SetPropertyInternal(propertyName, value);
return null;
case int arrayIndex:
MutableJsonElement element = _element.GetIndexElement(arrayIndex);
element.Set(value);
SetInternal(ref element, value);
return new DynamicData(element, _options);
}

throw new InvalidOperationException($"Tried to access indexer with an unsupported index type: {index}");
}

private void SetPropertyInternal(string name, object value)
{
switch (value)
{
case bool b:
_element = _element.SetProperty(name, b);
break;
case string s:
_element = _element.SetProperty(name, s);
break;
case byte b:
_element = _element.SetProperty(name, b);
break;
case sbyte sb:
_element = _element.SetProperty(name, sb);
break;
case short sh:
_element = _element.SetProperty(name, sh);
break;
case ushort us:
_element = _element.SetProperty(name, us);
break;
case int i:
_element = _element.SetProperty(name, i);
break;
case uint u:
_element = _element.SetProperty(name, u);
break;
case long l:
_element = _element.SetProperty(name, l);
break;
case ulong ul:
_element = _element.SetProperty(name, ul);
break;
case float f:
_element = _element.SetProperty(name, f);
break;
case double d:
_element = _element.SetProperty(name, d);
break;
case decimal d:
_element = _element.SetProperty(name, d);
break;
case DateTime d:
_element = _element.SetProperty(name, d);
break;
case DateTimeOffset d:
_element = _element.SetProperty(name, d);
break;
case Guid g:
_element = _element.SetProperty(name, g);
break;
case null:
_element = _element.SetPropertyNull(name);
break;
case JsonElement e:
_element = _element.SetProperty(name, e);
break;
default:
JsonElement element = ConvertType(value);
_element = _element.SetProperty(name, element);
break;
}
}

private void SetInternal(ref MutableJsonElement element, object value)
{
switch (value)
{
case bool b:
element.Set(b);
break;
case string s:
element.Set(s);
break;
case byte b:
element.Set(b);
break;
case sbyte sb:
element.Set(sb);
break;
case short sh:
element.Set(sh);
break;
case ushort us:
element.Set(us);
break;
case int i:
element.Set(i);
break;
case uint u:
element.Set(u);
break;
case long l:
element.Set(l);
break;
case ulong ul:
element.Set(ul);
break;
case float f:
element.Set(f);
break;
case double d:
element.Set(d);
break;
case decimal d:
element.Set(d);
break;
case DateTime d:
element.Set(d);
break;
case DateTimeOffset d:
element.Set(d);
break;
case Guid g:
element.Set(g);
break;
case null:
element.SetNull();
break;
case JsonElement e:
element.Set(e);
break;
default:
JsonElement jsonElement = ConvertType(value);
element.Set(jsonElement);
break;
}
}

private T? ConvertTo<T>()
{
JsonElement element = _element.GetJsonElement();
Expand Down
Loading