# Speeding up process time while archiving files

I asked this question on Stackoverflow, and was told I might have better luck here.

I'm new to and have created a basic file archiver. It works, and it does what it's suppose to do, but I think it's pretty slow. I added a simple benchmark in order to test the speed and ran it five times.

1. 50.7120707 seconds
2. 46.5686564 seconds
3. 50.2020197 seconds
4. 44.8384834 seconds
5. 44.5264522 seconds

So the average time for this process to run is 47.369536648 seconds. I understand that depending on the size of the files it's archiving and depending on how many files plays a big roll, so here's an image of the file sizes that I'm using as my test:

So the files really aren't to big, so I'm not sure if this is a good process time or not, it seems a little slow to me and I was wondering if there's anyway I can speed this up?

using System;
using System.IO;
using System.IO.Compression;

namespace ArchiveCreator
{
class Archive
{

//These static strings are used for
//information handling they will be
//color coordinated so you can see
//what kind of information is being
//passed to you
static string Success(string input)
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine(input);
return input;
}

static string Warn(string input)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(input);
return input;
}

static string Say(string input)
{
Console.ForegroundColor = ConsoleColor.DarkCyan;
Console.WriteLine(input);
return input;
}

static string FatalErr(string input)
{
Console.ForegroundColor = ConsoleColor.DarkRed;
Console.WriteLine(input);
return input;
}

static string MinorErr(string input)
{
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine(input);
return input;
}

//Main method
static void Main(string[] args)
{

//These variables are used to create a
//random string that will be used as the
//zip files name
var chars = "abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
var randFileName = new char[4];
var random = new Random();

//Create the zip file name
for (int i = 0; i < randFileName.Length; i++)
{
randFileName[i] = chars[random.Next(chars.Length)];
}
string finalString = new String(randFileName);

Say("Starting file extraction..");

string day = DateTime.Now.ToString("MM-dd-yy ");
string startDir = $"c:/users/{userName}/test_folder"; string zipDir =$"c:/users/{userName}/archive/{day}{finalString}.zip";
string dirName = $"c:/users/{userName}/archive"; //Check if the directory exists Say("Attempting to create archive directory.."); if (Directory.Exists(dirName)) { MinorErr("Directory already exists, resuming extraction process"); } else { //Create it if it doesn't Warn($"Creating archive directory here: {dirName}");
Directory.CreateDirectory(dirName);
Say("Directory created, resuming process..");
}

try
{
//Attempt to extract to zip file
Say($"Attempting to extract files into: {zipDir}"); ZipFile.CreateFromDirectory(startDir, zipDir); Success($"Extracted files successfully to: {zipDir}");
}
catch (Exception e)
{
//Catch any error that occurs during
//the archiving stage and log the error
//to a text file for further analysis
var programPath = System.Reflection.Assembly.GetExecutingAssembly();
FatalErr($"Something went wrong and the program cannot continue, exiting process with error code {e}.."); FatalErr("Writing error to file for further analysis."); File.WriteAllText($"{programPath}/log/errorlog.txt", e.ToString());
}

Say("Press enter to exit..");
}
}
}

• The answer you got on stack overflow is the same one I'd give which is changing the compression level to CompressionLevel.Fastest. You may be able to achieve faster results with a custom threading approach, but it would be significantly more work than just calling out to the library function which has already been tested and optimized. – forsvarir May 24 '16 at 7:38

As has been said in the stack overflow answer, the easiest way to improve performance is to use the alternate overload for ZipFile.CreateFromDirectory that supports you specifying the compression level.

ZipFile.CreateFromDirectory(startDir, zipDir, CompressionLevel.Fastest, false);


This tells the algorithm to prioritize speed over compression, so you trade size for time. Running some tests on my computer, it doesn't look like the compression algorithm has been used to maximize processor usage. It should be possible to improve the performance by using multiple threads to perform the compression, which is why zip products usually offer this as an option. Achieving this is however, a larger undertaking than just calling the library function so again it's a trade off between development time/complexity and run time.

As far as the rest of your code goes, I would consider moving your output methods behind an interface and implementing it in another class.

public interface IReporter {
string Success(string input);
string Warn(string input);
string Say(string input);
string FatalError(string input);
string MinorError(string input);
}

public class ConsoleReporter : IReporter {
public string Success(string input)
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine(input);
return input;
}
// etc
}


You can then instantiate a version of the concrete class and use it in your processing. This is a small change, however it means that if for example you decided to do a WPF version of your application it could easily be changed to output to a WPF control rather than the console, or you could have a version to write to a logfile rather than the console etc.

It's also a little odd that your output methods (Success, Warn, Say etc) return the string that's been passed into them. Would void be more appropriate. As far as I can see the return value is never used anywhere.

I'm not sure what your restrictions/goals are around the filename however you might also want to have a look at some alternates to GetRandomFileName or create unique filename with a given extension.

• I was unable to fully read your answer earlier, I really like the idea of the interface, I'm going to go ahead and implement that, I might also try multi threading, thank you for this answer. – 13aal May 24 '16 at 15:32