Files
git-tfs/GitTfsBenchmarks/Benchmarks/HashAndInsertObject.cs
T

174 lines
5.0 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using GitSharp.Core;
using Sep.Git.Tfs.Core;
using Sep.Git.Tfs.Util;
namespace Sep.Git.Tfs.Benchmarks
{
class HashAndInsertObject
{
private static readonly GitHelpers gitHelper = new GitHelpers(TextWriter.Null);
#region WithPureDotNet
[Benchmark]
public static void WithPureDotNet()
{
Run("clr", HashWithDotNet);
}
private static string HashWithDotNet(Stream data)
{
var bytes = new List<byte>();
bytes.AddRange(Encoding.ASCII.GetBytes("blob " + data.Length));
bytes.Add(0);
var binaryReader = new BinaryReader(data);
bytes.AddRange(binaryReader.ReadBytes((int)data.Length));
var byteArray = bytes.ToArray();
var sha1 = BitConverter.ToString(SHA1.Create().ComputeHash(byteArray)).Replace("-", "").ToLowerInvariant();
var sha1_0 = sha1.Substring(0, 2);
var sha1_1 = sha1.Substring(2);
var objectFile = CombinePaths(".git", "objects", sha1_0, sha1_1);
if(!File.Exists(objectFile))
{
Directory.CreateDirectory(Path.GetDirectoryName(objectFile));
using(var output = File.Create(objectFile))
{
using(var deflater = new DeflateStream(output, CompressionMode.Compress))
{
deflater.Write(byteArray, 0, byteArray.Length);
}
}
}
return sha1;
}
private static string CombinePaths(string part, params string [] parts)
{
foreach(var extraPart in parts)
{
part = Path.Combine(part, extraPart);
}
return part;
}
#endregion
#region WithExecGit
[Benchmark]
public static void WithExecGit()
{
Run("git", HashWithGit);
}
public static string HashWithGit(Stream file)
{
// Write the data to a file and insert that, so that git will handle any
// EOL and encoding issues.
using (var tempFile = new TemporaryFile())
{
using (var tempStream = File.Create(tempFile))
{
file.CopyTo(tempStream);
}
return HashWithGit(tempFile);
}
}
public static string HashWithGit(string filename)
{
string newHash = null;
gitHelper.CommandOutputPipe(stdout => newHash = stdout.ReadLine().Trim(),
"hash-object", "-w", filename);
return newHash;
}
#endregion
#region WithGitSharp
[Benchmark]
public static void WithGitSharp()
{
Run("gitsharp", HashWithGitSharp);
}
private static string HashWithGitSharp(Stream file)
{
var repository = new Repository(new DirectoryInfo(Path.Combine(Environment.CurrentDirectory, ".git")));
var writer = new ObjectWriter(repository);
return writer.WriteBlob(file.Length, file).ToString();
}
#endregion
#region setup & teardown
private static string originalCd;
public static void Reset()
{
originalCd = Environment.CurrentDirectory;
}
public static void Cleanup()
{
Environment.CurrentDirectory = originalCd;
}
public static void Check()
{
foreach (var file in GetExpectedFiles())
{
if (!File.Exists(file))
{
throw new Exception("Expected file " + file + " was not found!");
}
}
}
private static IEnumerable<string> GetExpectedFiles()
{
yield return ".git/objects/0e/44708cb3166a9f6c5c0a038bc7b2c0c2435e13";
}
private static IEnumerable<string> Split(string files)
{
var regex = new Regex("\\s+");
return regex.Split(files);
}
private static void Run(string name, Func<Stream, string> hashAndStore)
{
var dirName = Path.Combine(Environment.CurrentDirectory, "hash-object-" + name);
if(Directory.Exists(dirName)) Directory.Delete(dirName, true);
Directory.CreateDirectory(dirName);
Environment.CurrentDirectory = dirName;
gitHelper.CommandNoisy("init");
for (int i = 0; i < 300; i++)
{
hashAndStore(
MakeMemoryStream("teststring\r\nanother line\rafter just r\nafter just n"));
}
}
private static Stream MakeMemoryStream(string s)
{
return new MemoryStream(Encoding.ASCII.GetBytes(s));
}
#endregion
}
}