Skip to content

RoboCopy Benchmarking #192

Description

@RFBomb

I'm currently writing a custom IRoboCommand to orchestrate building a complex file batch that pulls from various folders and singular files to a final destination. As such, I've written an interface that has a method for CopyToAsync() to copy a file from source to destination asynchronously. I'm creating this thread to document some benchmarks, as RoboCopy is great at what it does.

I used ChatGPT and the microsoft documentation to create some async methods to handle the copying that reports via an IProgress<long> object. As well as a project developed to use CopyFileEx to perform the copy operation.

The benchmark for these tests was run in a console app in release mode, using a 334MB file. Each copy operation was performed 10x and the time report was the average result. My goal was to determine if a comparable time-to-copy could be achieve for a single file that falls within the current documentation recommendations I've been able to track down over a few days.

Note : This test was done on a console application targeting Net5.0 (as my work computer does not have VS2022 yet). Net6.0 benchmarks will happen in a followup comment.

CopyFileEx : https://github.com/RFBCodeWorks/CachedRoboCopy/blob/master/CachedRoboCopy/FileCopier.cs

static async Task NoProgressAsync(string source, string destination, int bufferSize = 81920)
{
    using (var reader = File.OpenRead(source))
    {
        using (var writer = File.OpenWrite(destination))
        {
            await reader.CopyToAsync(writer, bufferSize);
            writer.Dispose();
            reader.Dispose();
        }
    }
}

public static async Task ProgressAsync(string source, string destination, IProgress<long> progress, bool overwrite = false, CancellationToken token = default, int bufferSize = 81920)
{
    token.ThrowIfCancellationRequested();
    if (!File.Exists(source)) throw new FileNotFoundException("File not found : " + source);
    if (!overwrite && File.Exists(destination)) throw new IOException("Destination file already exists");
    if (progress is null) throw new ArgumentNullException(nameof(progress));
    int reportingInterval = 250;
    Stopwatch reportTimer = new Stopwatch();
    try
    {
        using (FileStream sourceStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, true))
        using (FileStream destinationStream = new FileStream(destination, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize, true))
        {
            byte[] buffer = new byte[bufferSize];
            long totalBytesRead = 0;
            int bytesRead;

            reportTimer.Start();
            while ((bytesRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length, token).ConfigureAwait(false)) > 0)
            {
                token.ThrowIfCancellationRequested();
                await destinationStream.WriteAsync(buffer, 0, bytesRead, token).ConfigureAwait(false);
                totalBytesRead += bytesRead;
                if (reportTimer.ElapsedMilliseconds >= reportingInterval)
                {
                    progress?.Report(totalBytesRead);
                    reportTimer.Restart();
                }
            }
            reportTimer.Stop();
            progress?.Report(totalBytesRead);
        }
    }
    catch (OperationCanceledException)
    {
        // If the operation was canceled, delete the destination file
        if (File.Exists(destination))
        {
            File.Delete(destination);
            Console.WriteLine($"File copy operation canceled. Destination file '{destination}' deleted.");
        }

        throw; // Re-throw the OperationCanceledException after handling
    }
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions