Skip to content

Commit f90c41c

Browse files
authored
Merge pull request #626 from qmfrederik/experiment/packfile-no-memory-mapping
GitPack: Don't use memory mapped streams when accessing pack files
2 parents 41696ba + c955e1f commit f90c41c

File tree

2 files changed

+65
-16
lines changed

2 files changed

+65
-16
lines changed

src/NerdBank.GitVersioning.Tests/ManagedGit/GitPackTests.cs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,15 @@ public void GetPackedObject()
6363
// This commit is not deltafied. It is stored as a .gz-compressed stream in the pack file.
6464
var zlibStream = Assert.IsType<ZLibStream>(commitStream);
6565
var deflateStream = Assert.IsType<DeflateStream>(zlibStream.BaseStream);
66-
var pooledStream = Assert.IsType<MemoryMappedStream>(deflateStream.BaseStream);
66+
67+
if (IntPtr.Size > 4)
68+
{
69+
var pooledStream = Assert.IsType<MemoryMappedStream>(deflateStream.BaseStream);
70+
}
71+
else
72+
{
73+
var pooledStream = Assert.IsType<FileStream>(deflateStream.BaseStream);
74+
}
6775

6876
Assert.Equal(222, commitStream.Length);
6977
Assert.Equal("/zgldANj+jvgOwlecnOKylZDVQg=", Convert.ToBase64String(sha.ComputeHash(commitStream)));
@@ -85,7 +93,15 @@ public void GetDeltafiedObject()
8593
var deltaStream = Assert.IsType<GitPackDeltafiedStream>(commitStream);
8694
var zlibStream = Assert.IsType<ZLibStream>(deltaStream.BaseStream);
8795
var deflateStream = Assert.IsType<DeflateStream>(zlibStream.BaseStream);
88-
var pooledStream = Assert.IsType<MemoryMappedStream>(deflateStream.BaseStream);
96+
97+
if (IntPtr.Size > 4)
98+
{
99+
var pooledStream = Assert.IsType<MemoryMappedStream>(deflateStream.BaseStream);
100+
}
101+
else
102+
{
103+
var directAccessStream = Assert.IsType<FileStream>(deflateStream.BaseStream);
104+
}
89105

90106
Assert.Equal(137, commitStream.Length);
91107
Assert.Equal("lZu/7nGb0n1UuO9SlPluFnSvj4o=", Convert.ToBase64String(sha.ComputeHash(commitStream)));
@@ -120,14 +136,24 @@ public void TryGetObjectTest()
120136
using (SHA1 sha = SHA1.Create())
121137
{
122138
Assert.True(gitPack.TryGetObject(GitObjectId.Parse("f5b401f40ad83f13030e946c9ea22cb54cb853cd"), "commit", out Stream commitStream));
139+
using (commitStream)
140+
{
141+
// This commit is not deltafied. It is stored as a .gz-compressed stream in the pack file.
142+
var zlibStream = Assert.IsType<ZLibStream>(commitStream);
143+
var deflateStream = Assert.IsType<DeflateStream>(zlibStream.BaseStream);
123144

124-
// This commit is not deltafied. It is stored as a .gz-compressed stream in the pack file.
125-
var zlibStream = Assert.IsType<ZLibStream>(commitStream);
126-
var deflateStream = Assert.IsType<DeflateStream>(zlibStream.BaseStream);
127-
var pooledStream = Assert.IsType<MemoryMappedStream>(deflateStream.BaseStream);
145+
if (IntPtr.Size > 4)
146+
{
147+
var pooledStream = Assert.IsType<MemoryMappedStream>(deflateStream.BaseStream);
148+
}
149+
else
150+
{
151+
var directAccessStream = Assert.IsType<FileStream>(deflateStream.BaseStream);
152+
}
128153

129-
Assert.Equal(222, commitStream.Length);
130-
Assert.Equal("/zgldANj+jvgOwlecnOKylZDVQg=", Convert.ToBase64String(sha.ComputeHash(commitStream)));
154+
Assert.Equal(222, commitStream.Length);
155+
Assert.Equal("/zgldANj+jvgOwlecnOKylZDVQg=", Convert.ToBase64String(sha.ComputeHash(commitStream)));
156+
}
131157
}
132158
}
133159

src/NerdBank.GitVersioning/ManagedGit/GitPack.cs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public class GitPack : IDisposable
3131
private readonly Func<FileStream> packStream;
3232
private readonly Lazy<FileStream> indexStream;
3333
private readonly GitPackCache cache;
34-
private MemoryMappedFile packFile;
35-
private MemoryMappedViewAccessor accessor;
34+
private MemoryMappedFile? packFile = null;
35+
private MemoryMappedViewAccessor? accessor = null;
3636

3737
// Maps GitObjectIds to offets in the git pack.
3838
private readonly Dictionary<GitObjectId, long> offsets = new Dictionary<GitObjectId, long>();
@@ -98,8 +98,11 @@ public GitPack(GetObjectFromRepositoryDelegate getObjectFromRepositoryDelegate,
9898
this.indexStream = indexStream ?? throw new ArgumentNullException(nameof(indexStream));
9999
this.cache = cache ?? new GitPackMemoryCache();
100100

101-
this.packFile = MemoryMappedFile.CreateFromFile(this.packStream(), mapName: null, 0, MemoryMappedFileAccess.Read, HandleInheritability.None, leaveOpen: false);
102-
this.accessor = this.packFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);
101+
if (IntPtr.Size > 4)
102+
{
103+
this.packFile = MemoryMappedFile.CreateFromFile(this.packStream(), mapName: null, 0, MemoryMappedFileAccess.Read, HandleInheritability.None, leaveOpen: false);
104+
this.accessor = this.packFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);
105+
}
103106
}
104107

105108
/// <summary>
@@ -202,7 +205,17 @@ public Stream GetObject(long offset, string objectType)
202205
}
203206

204207
var packStream = this.GetPackStream();
205-
Stream objectStream = GitPackReader.GetObject(this, packStream, offset, objectType, packObjectType);
208+
Stream objectStream;
209+
210+
try
211+
{
212+
objectStream = GitPackReader.GetObject(this, packStream, offset, objectType, packObjectType);
213+
}
214+
catch
215+
{
216+
packStream.Dispose();
217+
throw;
218+
}
206219

207220
return this.cache.Add(offset, objectStream);
208221
}
@@ -240,8 +253,8 @@ public void Dispose()
240253
this.indexReader.Value.Dispose();
241254
}
242255

243-
this.accessor.Dispose();
244-
this.packFile.Dispose();
256+
this.accessor?.Dispose();
257+
this.packFile?.Dispose();
245258
this.cache.Dispose();
246259
}
247260

@@ -265,7 +278,17 @@ public void Dispose()
265278

266279
private Stream GetPackStream()
267280
{
268-
return new MemoryMappedStream(this.accessor);
281+
// On 64-bit processes, we can use Memory Mapped Streams (the address space
282+
// will be large enough to map the entire packfile). On 32-bit processes,
283+
// we directly access the underlying stream.
284+
if (IntPtr.Size > 4)
285+
{
286+
return new MemoryMappedStream(this.accessor);
287+
}
288+
else
289+
{
290+
return this.packStream();
291+
}
269292
}
270293

271294
private GitPackIndexReader OpenIndex()

0 commit comments

Comments
 (0)