-
Notifications
You must be signed in to change notification settings - Fork 114
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
284 additions
and
6 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"redirections": [ | ||
{ | ||
"source_path": "Odata-docs/odatalib//v7/using-ut8jsonwriter-for-better-performance.md", | ||
"redirect_url": "/odata/odatalib/using-utf8jsonwriter-for-better-performance", | ||
"redirect_document_id": true | ||
} | ||
] | ||
} |
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,137 @@ | ||
--- | ||
title: "Disable writer validations" | ||
description: A guide on how to improve performance by disabling writer validations. | ||
date: 2024-01-23 | ||
ms.date: 1/23/2023 | ||
author: habbes | ||
ms.author: clhabins | ||
--- | ||
|
||
# Disable writer validations | ||
|
||
**Applies To**:[!INCLUDE[appliesto-webapi](../includes/appliesto-webapi-v8.md)][!INCLUDE[appliesto-webapi](../includes/appliesto-webapi-v7.md)][!INCLUDE[appliesto-odatalib](../includes/appliesto-odatalib-v7.md)] | ||
|
||
During serialization, the OData writer performs various validations to ensure that the payload is valid (e.g. no duplicate properties) and conforms to the schema (e.g. property type matches the entity type's definition). These validations introduce some overhead to the serialization process. If you know ahead of time that the payload you're writing is correct, you can disable one or more validations to improve performance. | ||
|
||
Use the [`ODataMessageWriterSettings.Validations`](/dotnet/api/microsoft.odata.odatamessagewritersettings.validations) property to configure which validations you want to enable or disable. | ||
|
||
You can disable all validations using [`ValidationKinds.None`](/dotnet/api/microsoft.odata.validationkinds): | ||
|
||
```csharp | ||
messageWriterSettings.Validations = ValidationKinds.None; | ||
``` | ||
|
||
You can selectively enable validations using the `&` operator: | ||
|
||
```csharp | ||
messageWriterSettings.Validations = ValidationKinds.ThrowOnDuplicatePropertyNames & ValidationKinds.ThrowIfTypeConflictsWithMetadata | ||
``` | ||
|
||
You can enable all validations using [`ValidationKinds.All`](/dotnet/api/microsoft.odata.validationkinds): | ||
|
||
```csharp | ||
messageWriterSettings.Validations = ValidationKinds.All; | ||
``` | ||
|
||
To learn more about different validation options, consult the [`ValidationKinds` enum documentation](/dotnet/api/microsoft.odata.validationkinds). | ||
|
||
## Disabling writer validations when using `Microsoft.OData.Core` library directly | ||
|
||
When using the core library directly, you pass the [`ODataMessageWriterSettings`](/dotnet/api/microsoft.odata.odatamessagewritersettings) to the [`ODataMessageWriter`](/dotnet/api/microsoft.odata.odatamessagewriter) constructor. | ||
|
||
```csharp | ||
ODataMessageWriterSettings settings = new ODataMessageWriterSettings | ||
{ | ||
ODataUri = new ODataUri() { /* ... */ }, | ||
Validations = ValidationKinds.None | ||
}; | ||
|
||
ODataMessageWriter writer = new ODataMessageWriter(odataMessage, settings, edmModel); | ||
|
||
// ... | ||
``` | ||
|
||
## Disabling writer validations when using `Microsoft.AspNetCore.OData` 8 library | ||
|
||
In `Microsoft.AspNetCore.OData` 8, you can pass a service configuration action as the third argument of `AddRouteComponents`. Use | ||
this to inject a request-scoped instance of `ODataMessageWriterSettings` - with the desired options - to the service container: | ||
|
||
```csharp | ||
services | ||
.AddControllers() | ||
.AddOData(options => | ||
options.AddRouteComponents( | ||
routePrefix: "routePrefix", | ||
model: edmModel, | ||
configurateServices: container => | ||
{ | ||
container.AddScoped<ODataMessageWriterSettings>(_ => new ODataMessageWriterSettings | ||
{ | ||
Validations = ValidationKinds.None | ||
}) | ||
})); | ||
``` | ||
|
||
## Disabling writer validations when using `Microsoft.AspNetCore.OData` 7 library | ||
|
||
In `Microsoft.AspNetCore.OData` 7, you can pass a service configuration action to the `MapODataRoute` and `MapODataServiceRoute` methods. | ||
Use this to inject a request-scoped instance of `ODataMessageWriterSettings` to the service container. | ||
|
||
### Using endpoint routing | ||
|
||
```csharp | ||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) | ||
{ | ||
|
||
// ... | ||
app.UseEndpoints(endpoints => | ||
{ | ||
endpoints.MapODataRoute( | ||
routeName: "odata", | ||
routePrefix: “odata”, | ||
configureAction: container => | ||
{ | ||
container.AddService<ODataMessageWriterSettings>(Microsoft.OData.ServiceLifetime.Scoped, _ => new ODataMessageWriterSettings | ||
{ | ||
Validations = ValidationKinds.None | ||
}); | ||
|
||
container.AddService(Microsoft.OData.ServiceLifetime.Singleton, _ => model); | ||
container.AddService<IEnumerable<IODataRoutingConvention>>(Microsoft.OData.ServiceLifetime.Singleton, | ||
sp => ODataRoutingConventions.CreateDefaultWithAttributeRouting("odata", sp)); | ||
}); | ||
}); | ||
|
||
// ... | ||
} | ||
``` | ||
|
||
### Using MVC routing | ||
|
||
```csharp | ||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) | ||
{ | ||
IEdmModel model = GetEdmModel(); | ||
|
||
app.UseMvc(builder => | ||
{ | ||
builder.Select().Expand().Filter().OrderBy().MaxTop(100).Count(); | ||
|
||
builder.MapODataServiceRoute( | ||
routeName: "odata", | ||
routePrefix: "odata", | ||
configureAction: container => | ||
{ | ||
container.AddService<ODataMessageWriterSettings>(Microsoft.OData.ServiceLifetime.Scope, _ => new ODataMessageWriterSettings | ||
{ | ||
Validations = ValidationKinds.None | ||
}); | ||
|
||
container.AddService(Microsoft.OData.ServiceLifetime.Singleton, _ => model) | ||
.AddService<IEnumerable<IODataRoutingConvention>>(Microsoft.OData.ServiceLifetime.Singleton, _ => | ||
ODataRoutingConventions.CreateDefaultWithAttributeRouting("odata", builder)); | ||
}); | ||
}); | ||
} | ||
``` |
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,52 @@ | ||
--- | ||
title: "Mark the EDM model as immutable" | ||
description: A guide on how to improve performance by marking the EDM model as immutable. | ||
date: 2023-08-11 | ||
ms.date: 8/11/2023 | ||
author: habbes | ||
ms.author: clhabins | ||
--- | ||
|
||
# Mark the EDM model as immutable | ||
|
||
**Applies To**:[!INCLUDE[appliesto-webapi](../includes/appliesto-webapi-v8.md)][!INCLUDE[appliesto-webapi](../includes/appliesto-webapi-v7.md)][!INCLUDE[appliesto-odatalib](../includes/appliesto-odatalib-v7.md)] | ||
|
||
OData libraries at times perform multiple lookups in the EDM model when processing a request. Some of these lookups may be expensive, especially for large models with a lot of schema elements. | ||
We have some optimizations in place to reduce the performance overhead of these internal lookups, but some of these optimizations are only applicable if the library knows that the EDM model will not change. You can enable these optimizations by explicitly marking your EDM as immutable by calling the `MarkAsImmutable` method, which is an extension method in the `Microsoft.OData.Edm` namespace. | ||
|
||
```csharp | ||
using Microsoft.OData.Edm; | ||
|
||
IEdmModel GetEdmModel() | ||
{ | ||
var modelBuilder = new ODataConventionModelBuilder(); | ||
modelBuilder.EntitySet<Person>("People"); | ||
IEdmModel model = modelBuilder.GetEdmModel(); | ||
model.MarkAsImmutable(); | ||
return model; | ||
} | ||
``` | ||
|
||
It is recommended to mark the EDM model as immutable since most applications do not modify the model after it has been constructed. | ||
|
||
It is however important to note that the library makes no effort to ensure or verify that the model doesn't change after calling this method. It is the responsibility of the developer to ensure that the model is not modified after the `MarkAsImmutable` method is called. Modifying the model after `MarkAsImmutable` method has been called may lead to unexpected behavior. | ||
|
||
The following code snippet shows an example of incorrect usage of this method: | ||
|
||
```csharp | ||
using Microsoft.OData.Edm; | ||
|
||
IEdmModel GetEdmModel() | ||
{ | ||
var model = new EdmModel(); | ||
var personType = new EdmEntityType("Sample.NS", "Person"); | ||
personType.AddKeys(personType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, isNullable: false)); | ||
model.MarkAsImmutable(); | ||
|
||
var addressType = new EdmComplexType("Sample.NS", "Address"); | ||
// DO NOT DO THIS! Modifying the model after calling MarkAsImmutable | ||
// can lead to unexpected behavior. | ||
model.AddElement(addressType); | ||
return model; | ||
} | ||
``` |
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,14 @@ | ||
--- | ||
title: "Performance Guidelines" | ||
description: Overview of performance improvements tips and guidelines when using OData libraries. | ||
date: 2024-01-23 | ||
ms.date: 1/23/2023 | ||
author: habbes | ||
ms.author: clhabins | ||
--- | ||
|
||
# Performance guidelines | ||
|
||
**Applies To**:[!INCLUDE[appliesto-webapi](../includes/appliesto-webapi-v8.md)][!INCLUDE[appliesto-webapi](../includes/appliesto-webapi-v7.md)][!INCLUDE[appliesto-odatalib](../includes/appliesto-odatalib-v7.md)] | ||
|
||
This section contains a series of articles that provide tips and guidelines for improving performance when working with OData libraries. If your OData service is experiencing performance issues, consider implementing the guidelines in this section and measure performance using appropriate benchmarks and metrics. |
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,22 @@ | ||
--- | ||
title: "Use Utf8JsonWriter" | ||
description: A guide on how to improve performance using Utf8JsonWriter. | ||
date: 2024-01-23 | ||
ms.date: 1/23/2024 | ||
author: habbes | ||
ms.author: clhabins | ||
--- | ||
|
||
# Use `Utf8JsonWriter` | ||
|
||
**Applies To**:[!INCLUDE[appliesto-webapi](../includes/appliesto-webapi-v8.md)][!INCLUDE[appliesto-webapi](../includes/appliesto-webapi-v7.md)][!INCLUDE[appliesto-odatalib](../includes/appliesto-odatalib-v7.md)] | ||
|
||
The OData core library implements a wrapper on top of the `Utf8JsonWriter` to complement the default JSON writer. This writer offers better performance and fewer memory allocations compared to using the JSON writer that's used by default in `Microsoft.OData.Core`. | ||
|
||
To enable `Utf8JsonWriter`, check out any of the following guides depending on the library you are using in your application: | ||
|
||
- [Enable `Ut8fJsonWriter` when using `Microsoft.OData.Core` library directly](/odata/odatalib/using-utf8jsonwriter-for-better-performance) | ||
- [Enable `Utf8JsonWriter` when using `Microsoft.AspNetCore.OData` 8.x library](/odata/webapi-8/tutorials/using-utf8jsonwriter-to-improve-serialization-performance) | ||
- [Enable `Ut8fJsonWriter` when using `Microsoft.AspNetCore.OData` 7.x library](/odata/webapi/using-utf8jsonwriter-to-improve-serialization-performance) | ||
|
||
When using `Utf8JsonWriter`, consider using the [`UnsafeRelaxedJsonEscaping`](/dotnet/api/system.text.encodings.web.javascriptencoder.unsaferelaxedjsonescaping) encoder to perform escaping as described [here](/odata/odatalib/using-utf8jsonwriter-for-better-performance#choosing-a-javascriptencoder). This encoder is more relaxed and escapes fewer characters. This can improve performance over the default encoder which escapes more characters. Frequent escaping of large strings may result in additional performance and memory overhead. |
32 changes: 32 additions & 0 deletions
32
...webapi-8/tutorials/using-utf8jsonwriter-to-improve-serialization-performance.md
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,32 @@ | ||
--- | ||
title: "Using Utf8JsonWriter to improve serialization performance" | ||
description: Learn how to configure ASP.NET Core OData 8 to use Utf8JsonWriter to improve serialization performance. | ||
date: 2023-08-11 | ||
ms.date: 08/11/2023 | ||
author: habbes | ||
ms.author: clhabins | ||
--- | ||
|
||
# Using Utf8JsonWriter to improve serialization performance | ||
|
||
**Applies To**:[!INCLUDE[appliesto-webapi](../../includes/appliesto-webapi-v8.md)] | ||
|
||
`Microsoft.OData.Core` version 7.12.2 introduced a new JSON writer that’s based on .NET’s [`Utf8JsonWriter`](/dotnet/api/system.text.json.utf8jsonwriter). This writer offers better performance than the JSON writer that is used by default in `Microsoft.OData.Core`. Reference `Microsoft.AspNetCore.OData 8.0.11` or higher to use the new writer. To learn more, [visit this page](../../odatalib/v7/using-utf8jsonwriter-for-better-performance.md). In this article, we are going to show you how to configure your ASP.NET Core OData application to use the `Utf8JsonWriter`. | ||
|
||
You register OData services through use of `AddRouteComponents` method. To use the `Utf8JsonWriter`, register the `IStreamBasedJsonWriterFactory` service. The `Microsoft.OData.Core` library provides a default implementation of this interface - `DefaultStreamBasedJsonWriterFactory`. | ||
|
||
Here's how you can do this in your application. In your application startup code, import the `Microsoft.OData.Json` namespace and register the `IStreamBasedJsonWriterFactory` service as follows: | ||
|
||
```c# | ||
services.AddControllers() | ||
.AddOData(options => | ||
options.AddRouteCompontents( | ||
routePrefix: "odata", | ||
model: model, | ||
configureServices: services => | ||
{ | ||
services.AddSingleton<IStreamBasedJsonWriterFactory>(_ => DefaultStreamBasedJsonWriterFactory.Default); | ||
}); | ||
``` | ||
|
||
That is all that's required to substitute the default JSON writer with the `Utf8JsonWriter`. |