-
Notifications
You must be signed in to change notification settings - Fork 17
Upgrade to .NET 9 and update dependencies #15
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
base: main
Are you sure you want to change the base?
Conversation
- Upgrade target framework from net8.0 to net9.0│ - Update GirCore packages to version 0.6.3 (Adw, Gtk-4.0, WebKit-6.0)│ - Update Microsoft packages to version 9.0.8 (Components.WebView, Extensions.Logging.Console, Extensions.Hosting)│ - Fix MemoryInputStream creation using GLib.Bytes.New instead of deprecated NewFromData method│ - Remove custom InputStream workaround class, no longer needed with updated GirCore - Add missing GLib.Internal using statement│ - Improve null safety with explicit nullable array parameters
WebKitGtk/BlazorWebView.cs
Outdated
var streamPtr = MemoryInputStream.NewFromData(ref ms.GetBuffer()[0], (uint)ms.Length, _ => { }); | ||
var inputStream = new InputStream(streamPtr, false); | ||
request.Finish(inputStream, ms.Length, headers["Content-Type"]); | ||
byte[] data = ms.ToArray(); |
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.
Hello @loribao
AsSpan(0, (int)memoryStream.Length)
provides a zero-copy slice of the bufferSpan<T>
is a modern .NET construct that enables high-performance, allocation-free operations- This approach avoids creating intermediate objects while maintaining memory safety
The key difference:
ToArray()
creates a copy of the data in memoryGetBuffer() + AsSpan()
provides direct access to the underlying buffer without additional allocations
For large data streams, this can result in significant performance improvements and reduced memory pressure.
You can find the optimized version here:
https://github.com/czirok/apps/blob/f237a9b8874eac208b0503f237f2cf2218c070df/src/WebKit.BlazorWebView.GirCore/src/WebKitWebViewManager.cs#L123
Hi @czirok, Thanks for the excellent performance optimization suggestions! I implemented the recommended changes and validated them with extensive benchmarking. Changes MadeImplemented ArrayPool for buffer reuse
Zero-copy operations with Span
Optimized GLib.Bytes creation
Performance ValidationI created benchmarks in the Benchmark results demonstrate:
The implementation is now ready and maintains backward compatibility while delivering the suggested performance improvements. |
Applied performance optimizations suggested in PR feedback: - Use System.Buffers.ArrayPool<byte> for buffer reuse instead of allocating new arrays - Implement Span<byte> for zero-copy buffer operations - Use GLib.Bytes.New(span) to avoid unnecessary memory copies - Maintain proper buffer lifecycle with try/finally for ArrayPool.Return Validated performance improvements with benchmark testing in benchmark/handleurischeme branch.
bae674d
to
1e6bb04
Compare
const int bufferSize = 64 * 1024; | ||
byte[] buffer = System.Buffers.ArrayPool<byte>.Shared.Rent(bufferSize); | ||
|
||
var memoryInputStream = Gio.MemoryInputStream.New(); | ||
long totalLength = 0; | ||
|
||
try | ||
{ | ||
while (true) | ||
{ | ||
int read = content.Read(buffer, 0, bufferSize); | ||
if (read <= 0) | ||
break; | ||
|
||
var span = new Span<byte>(buffer, 0, read); | ||
using var bytes = GLib.Bytes.New(span); | ||
memoryInputStream.AddBytes(bytes); | ||
totalLength += read; | ||
} | ||
} | ||
finally | ||
{ | ||
System.Buffers.ArrayPool<byte>.Shared.Return(buffer); | ||
} | ||
request.Finish(memoryInputStream, totalLength, headers["Content-Type"]); |
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 think I'd prefer to maintain the workaround.
Summary
Test plan