Coding Faster with dotNetTips.com Spargine 8:  May 2024 Release

I am delighted to announce the release (v2024.8.5.1) of Spargine 8 on May 5th, 2024. Spargine, my open-source project, now offers NuGet packages for .NET 8. This update introduces new methods, benchmarks, and unit tests. Notably, this release includes speed enhancements informed by benchmark tests outlined in the 4th edition of Rock Your Code: Code & App Performance for Microsoft .NET, available on Amazon. These enhancements have been integrated across all my projects, many of which are currently in production. I encourage you to explore these updates and share any feedback or suggestions for further improvements.

GitHub: https://github.com/RealDotNetDave/dotNetTips.Spargine.8/releases

NuGet: http://bit.ly/dotNetDaveNuGet

You can access all the performance data for these assemblies on GitHub. I continually seek assistance with these projects, especially in writing additional unit tests. If you are interested in contributing, please don’t hesitate to contact me via email at dotnetdave@live.com. Your support and collaboration are highly appreciated!

New Features

CopyFile Method

I’ve implemented a new method called CopyFile() in the FileHelper class. If you’ve utilized the CopyTo() method in .NET for file copying, you may have encountered an issue: there’s no built-in way to track the progress of the file copy, making it difficult to provide feedback to users. This new method addresses that by allowing you to specify a callback to receive progress updates.

To utilize it, begin by creating a method like the one outlined below to capture the status of the file copy:

private static CopyProgressResult CopyProgressCallback(long totalFileSize,
    long totalBytesTransferred,
    long streamSize,
    long streamBytesTransferred,
    uint dwStreamNumber,
    CopyProgressCallbackReason dwCallbackReason,
    IntPtr hSourceFile,
    IntPtr hDestinationFile,
    IntPtr lpData)
{
    Trace.WriteLine($"TotalFileSize:{totalFileSize}");
    Trace.WriteLine($"TotalBytesTransferred:{totalBytesTransferred}");
    Trace.WriteLine($"StreamSize:{streamSize}");
    Trace.WriteLine($"StreamBytesTransferred:{streamBytesTransferred}");
    Trace.WriteLine($"dwStreamNumber:{dwStreamNumber}");
    Trace.WriteLine($"CopyProgressCallbackReason:{dwCallbackReason}");

    return CopyProgressResult.Continue;
}

Here’s how you can call the CopyFile() method:

CopyProgressRoutine callback = new CopyProgressRoutine(CopyProgressCallback);
var result = FileHelper.CopyFile(file: file, destination: directory, progressCallback: callback);

Below are the results of the CopyProgressCallback method when testing this in a unit test:

TotalFileSize:2048
TotalBytesTransferred:0
StreamSize:2048
StreamBytesTransferred:0
dwStreamNumber:1
CopyProgressCallbackReason:StreamSwitch
TotalFileSize:2048
TotalBytesTransferred:2048
StreamSize:2048
StreamBytesTransferred:2048
dwStreamNumber:1
CopyProgressCallbackReason:ChunkFinished

FastCount Method

I’ve implemented a new method named FastCount() within EnumerableExtensions. This method returns the count of an IList<T> collection while also ensuring that the collection is not null.

FastHashData Method

I’ve introduced a new method called FastHashData() to ArrayExtensions. This method efficiently hashes an array of bytes using SHA256. Here’s an example of how to utilize it:

var result = byteArray.FastHashData();

In a test scenario, converting the result into a string would appear as follows:

84ff92691f909a05b224e1c56abb4864f01b4f8e3c854e4bb4c7baf1d3f6d652

Updated Methods

Here are the methods that have been updated in this version of Spargine:

  • DirectoryHelper.SafeFileSearch(): Performs a safe file search, ignoring errors accessing directories, usually for security reasons.
  • EnumerableExtensions.AddDistinct(): Adds an item to an IEnumerable<T> collection if that item does not already exist.
  • EnumerableExtensions.Create(): Converts an IEnumerable<T> collection into a Collection.
  • EnumerableExtensions.FastAny(): Determines if any items exist in an IEnumerable<T> collection using a predicate.
  • FastStringBuilder.BytesToString(): Converts bytes to a string using the StringBuilder from an ObjectPool for optimal performance.
  • FastStringBuilder.ConcatStrings(): Converts an array of strings to a string using the StringBuilder from an ObjectPool for optimal performance.
  • FileHelper.DeleteFiles(): Attempts to delete files and returns the names of deleted files along with any error messages for files that could not be deleted.
  • FileHelper.MoveFile(): Moves the file with retries and options.
  • JsonSerialization.DeserializeFromFile(): Deserializes JSON from a file into an object.
  • JsonSerialization.SerializeToFile(): Serializes an object to JSON and saves it to a file.
  • ListExtensions.PerformAction(): Performs an action on the items in a List<T>.
  • RandomData.GeneratePersonRef(): Generates a Person reference type with generated values.
  • Validator.ArgumentItemsExists(): Validates that there are items in a IReadOnlyList<T> or a IReadOnlyCollection<T>.

These updates aim to enhance performance and functionality, ensuring smoother operation and better user experience.

Performance Improvements

With each Spargine release, I strive to enhance performance. Here are some of the methods demonstrating notable performance improvements:

  • ArrayExtensions.Clone() for reference types: Performance increase of 1.065 times.
  • ArrayExtensions.PerformAction() for reference types: Performance increase of 1.027 times.
  • EnumerableExtensions.ToDelimitedString(): Performance increase of 1.019 times.
  • JsonSerialization.Deserialize() for a list of reference types: Performance increase of 1.34 times.
  • JsonSerialization.Deserialize() for a record: Performance increase of 1.37 times.
  • JsonSerialization.Serialize() for a record type: Performance increase of 1.07 times.
  • JsonSerialization.Serialize() for a reference type: Performance increase of 1.094 times.
  • ListExtensions.HasItems(): Significant performance increase of 33,056 times!
  • RandomData serialization from JSON utilizing PersonJsonSerializerContext: Performance increase of 1.203 times.
  • StringExtension.DefaultIfNullOrEmpty(): Performance increase of 2.75 times.

Summary

I trust that these methods in Spargine will be of greater utility to your projects. The benchmark results are available on GitHub, and you can access the links to them in the ReadMe file. If you require additional functionality, feel free to submit a pull request. I would love to hear your feedback and suggestions; kindly post them in the comments section below.

Keep coding better and faster geeks!

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.