Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
4566936c
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4566936c
编写于
5月 15, 2017
作者:
S
Sam Harwell
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Reduce GC overhead of memory mapped files
上级
e758647b
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
93 addition
and
82 deletion
+93
-82
src/Workspaces/Core/Desktop/Workspace/Host/TemporaryStorage/TemporaryStorageServiceFactory.CopiedMemoryMappedViewHandle.cs
...raryStorageServiceFactory.CopiedMemoryMappedViewHandle.cs
+57
-0
src/Workspaces/Core/Desktop/Workspace/Host/TemporaryStorage/TemporaryStorageServiceFactory.MemoryMappedInfo.cs
...torage/TemporaryStorageServiceFactory.MemoryMappedInfo.cs
+35
-82
src/Workspaces/Core/Desktop/Workspaces.Desktop.csproj
src/Workspaces/Core/Desktop/Workspaces.Desktop.csproj
+1
-0
未找到文件。
src/Workspaces/Core/Desktop/Workspace/Host/TemporaryStorage/TemporaryStorageServiceFactory.CopiedMemoryMappedViewHandle.cs
0 → 100644
浏览文件 @
4566936c
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using
System
;
using
System.Runtime.CompilerServices
;
using
System.Runtime.InteropServices
;
using
Microsoft.Win32.SafeHandles
;
namespace
Microsoft.CodeAnalysis.Host
{
internal
partial
class
TemporaryStorageServiceFactory
{
/// <summary>
/// This critical handle increments the reference count of a <see cref="SafeMemoryMappedViewHandle"/>. The view
/// will be released when it is disposed <em>and</em> all pointers acquired through
/// <see cref="SafeBuffer.AcquirePointer"/> (which this class uses) are released.
/// </summary>
/// <remarks>
/// <para><see cref="CriticalHandle"/> types are not reference counted, and are thus somewhat limited in their
/// usefulness. However, this handle class has tightly restricted accessibility and is only used by managed
/// code which does not rely on it counting references.</para>
/// </remarks>
private
unsafe
sealed
class
CopiedMemoryMappedViewHandle
:
CriticalHandleZeroOrMinusOneIsInvalid
{
private
readonly
SafeMemoryMappedViewHandle
_viewHandle
;
public
CopiedMemoryMappedViewHandle
(
SafeMemoryMappedViewHandle
viewHandle
)
{
_viewHandle
=
viewHandle
;
byte
*
pointer
=
null
;
// The following code uses a constrained execution region (CER) to ensure that the code ends up in one
// of the following states, even in the presence of asynchronous exceptions like ThreadAbortException:
//
// 1. The pointer is not acquired, and the current handle is invalid (thus will not be released)
// 2. The pointer is acquired, and the current handle is fully initialized for later cleanup
RuntimeHelpers
.
PrepareConstrainedRegions
();
try
{
viewHandle
.
AcquirePointer
(
ref
pointer
);
}
finally
{
SetHandle
((
IntPtr
)
pointer
);
}
}
public
byte
*
Pointer
=>
(
byte
*)
handle
;
protected
override
bool
ReleaseHandle
()
{
_viewHandle
.
ReleasePointer
();
return
true
;
}
}
}
}
src/Workspaces/Core/Desktop/Workspace/Host/TemporaryStorage/TemporaryStorageServiceFactory.MemoryMappedInfo.cs
浏览文件 @
4566936c
...
@@ -22,16 +22,27 @@ internal sealed class MemoryMappedInfo : IDisposable
...
@@ -22,16 +22,27 @@ internal sealed class MemoryMappedInfo : IDisposable
{
{
private
readonly
string
_name
;
private
readonly
string
_name
;
private
readonly
long
_size
;
private
readonly
long
_size
;
private
readonly
MemoryMappedFile
_memoryMappedFile
;
/// <summary>
/// <summary>
///
ref count of stream given out
///
The memory mapped file.
/// </summary>
/// </summary>
private
int
_streamCount
;
/// <remarks>
/// <para>It is possible for this accessor to be disposed prior to the view and/or the streams which use it.
/// However, the operating system does not actually close the views which are in use until the view handles
/// are closed as well, even if the <see cref="MemoryMappedFile"/> is disposed first.</para>
/// </remarks>
private
readonly
MemoryMappedFile
_memoryMappedFile
;
/// <summary>
/// <summary>
/// actual memory accessor that owns the VM
/// actual memory accessor that owns the VM
/// </summary>
/// </summary>
/// <remarks>
/// <para>It is possible for this accessor to be disposed prior to the streams which use it. However, the
/// streams interact directly with the underlying memory buffer, and keep a
/// <see cref="CopiedMemoryMappedViewHandle"/> to prevent that buffer from being released while still in
/// use. The <see cref="SafeHandle"/> used by this accessor is reference counted, and is not finally
/// released until the reference count reaches zero.</para>
/// </remarks>
private
MemoryMappedViewAccessor
_accessor
;
private
MemoryMappedViewAccessor
_accessor
;
public
MemoryMappedInfo
(
long
size
)
public
MemoryMappedInfo
(
long
size
)
...
@@ -40,9 +51,6 @@ public MemoryMappedInfo(long size)
...
@@ -40,9 +51,6 @@ public MemoryMappedInfo(long size)
_size
=
size
;
_size
=
size
;
_memoryMappedFile
=
MemoryMappedFile
.
CreateNew
(
_name
,
size
);
_memoryMappedFile
=
MemoryMappedFile
.
CreateNew
(
_name
,
size
);
_streamCount
=
0
;
_accessor
=
null
;
}
}
public
MemoryMappedInfo
(
string
name
,
long
size
)
public
MemoryMappedInfo
(
string
name
,
long
size
)
...
@@ -51,9 +59,6 @@ public MemoryMappedInfo(string name, long size)
...
@@ -51,9 +59,6 @@ public MemoryMappedInfo(string name, long size)
_size
=
size
;
_size
=
size
;
_memoryMappedFile
=
MemoryMappedFile
.
OpenExisting
(
_name
);
_memoryMappedFile
=
MemoryMappedFile
.
OpenExisting
(
_name
);
_streamCount
=
0
;
_accessor
=
null
;
}
}
/// <summary>
/// <summary>
...
@@ -81,7 +86,7 @@ public Stream CreateReadableStream()
...
@@ -81,7 +86,7 @@ public Stream CreateReadableStream()
// CreateViewStream is not guaranteed to be thread-safe
// CreateViewStream is not guaranteed to be thread-safe
lock
(
_memoryMappedFile
)
lock
(
_memoryMappedFile
)
{
{
if
(
_
streamCount
==
0
)
if
(
_
accessor
==
null
)
{
{
try
try
{
{
...
@@ -97,8 +102,8 @@ public Stream CreateReadableStream()
...
@@ -97,8 +102,8 @@ public Stream CreateReadableStream()
}
}
}
}
_streamCount
++
;
Contract
.
Assert
(
_accessor
.
CanRead
)
;
return
new
SharedReadableStream
(
this
,
_accessor
,
_size
);
return
new
SharedReadableStream
(
this
,
new
CopiedMemoryMappedViewHandle
(
_accessor
.
SafeMemoryMappedViewHandle
),
_accessor
.
PointerOffset
,
_size
);
}
}
}
}
...
@@ -115,24 +120,6 @@ public Stream CreateWritableStream()
...
@@ -115,24 +120,6 @@ public Stream CreateWritableStream()
}
}
}
}
private
void
StreamDisposed
()
{
lock
(
_memoryMappedFile
)
{
_streamCount
--;
if
(
_streamCount
==
0
&&
_accessor
!=
null
)
{
_accessor
.
Dispose
();
_accessor
=
null
;
}
}
}
~
MemoryMappedInfo
()
{
Dispose
(
false
);
}
public
void
Dispose
()
public
void
Dispose
()
{
{
Dispose
(
true
);
Dispose
(
true
);
...
@@ -141,25 +128,21 @@ public void Dispose()
...
@@ -141,25 +128,21 @@ public void Dispose()
private
void
Dispose
(
bool
disposing
)
private
void
Dispose
(
bool
disposing
)
{
{
lock
(
_memoryMappedFile
)
if
(
disposing
)
{
{
if
(
_accessor
!=
null
)
lock
(
_memoryMappedFile
)
{
{
// dispose accessor it owns.
if
(
_accessor
!=
null
)
// if someone explicitly called Dispose when streams given out are not
{
// disposed yet, the accessor each stream has will simply stop working.
// (see remarks on accessor for relation between _accessor and the streams)
//
_accessor
.
Dispose
();
// it is caller's responsibility to make sure all streams it got from
_accessor
=
null
;
// the temporary storage are disposed before calling dispose on the storage.
}
//
// otherwise, finalizer will take care of disposing stuff as we used to be.
_accessor
.
Dispose
();
_accessor
=
null
;
}
}
}
// Dispose the memoryMappedFile
// (see remarks on accessor for relation between _memoryMappedFile and the views/streams)
_memoryMappedFile
.
Dispose
();
_memoryMappedFile
.
Dispose
();
}
}
}
public
static
string
CreateUniqueName
(
long
size
)
public
static
string
CreateUniqueName
(
long
size
)
...
@@ -169,31 +152,19 @@ public static string CreateUniqueName(long size)
...
@@ -169,31 +152,19 @@ public static string CreateUniqueName(long size)
private
unsafe
sealed
class
SharedReadableStream
:
Stream
,
ISupportDirectMemoryAccess
private
unsafe
sealed
class
SharedReadableStream
:
Stream
,
ISupportDirectMemoryAccess
{
{
private
readonly
MemoryMappedViewAccessor
_accessor
;
private
readonly
CopiedMemoryMappedViewHandle
_handle
;
private
MemoryMappedInfo
_owner
;
private
byte
*
_start
;
private
byte
*
_start
;
private
byte
*
_current
;
private
byte
*
_current
;
private
readonly
byte
*
_end
;
private
readonly
byte
*
_end
;
public
SharedReadableStream
(
MemoryMappedInfo
owner
,
MemoryMappedViewAccessor
accessor
,
long
length
)
public
SharedReadableStream
(
MemoryMappedInfo
owner
,
CopiedMemoryMappedViewHandle
handle
,
long
offset
,
long
length
)
{
{
Contract
.
Assert
(
accessor
.
CanRead
);
_handle
=
handle
;
_current
=
_start
=
handle
.
Pointer
+
offset
;
_owner
=
owner
;
_accessor
=
accessor
;
_current
=
_start
=
AcquirePointer
(
accessor
);
_end
=
checked
(
_start
+
length
);
_end
=
checked
(
_start
+
length
);
}
}
~
SharedReadableStream
()
{
// we don't have control on stream we give out to others such as
// compiler (ImageOnlyMetadataReference), make sure we dispose resource
// at the end if Disposed is not called explicitly.
Dispose
(
false
);
}
public
override
bool
CanRead
public
override
bool
CanRead
{
{
get
get
...
@@ -326,17 +297,12 @@ protected override void Dispose(bool disposing)
...
@@ -326,17 +297,12 @@ protected override void Dispose(bool disposing)
{
{
base
.
Dispose
(
disposing
);
base
.
Dispose
(
disposing
);
if
(
_start
!=
null
)
if
(
disposing
)
{
{
_accessor
.
SafeMemoryMappedViewHandle
.
ReleasePointer
();
_handle
.
Dispose
();
_start
=
null
;
}
}
if
(
_owner
!=
null
)
_start
=
null
;
{
_owner
.
StreamDisposed
();
_owner
=
null
;
}
}
}
/// <summary>
/// <summary>
...
@@ -346,19 +312,6 @@ public IntPtr GetPointer()
...
@@ -346,19 +312,6 @@ public IntPtr GetPointer()
{
{
return
(
IntPtr
)
_start
;
return
(
IntPtr
)
_start
;
}
}
/// <summary>
/// Acquire the fixed pointer to the start of the memory mapped view.
/// The pointer will be released during <see cref="Dispose(bool)"/>
/// </summary>
/// <returns>The pointer to the start of the memory mapped view. The pointer is valid, and remains fixed for the lifetime of this object.</returns>
private
static
byte
*
AcquirePointer
(
MemoryMappedViewAccessor
accessor
)
{
byte
*
ptr
=
null
;
accessor
.
SafeMemoryMappedViewHandle
.
AcquirePointer
(
ref
ptr
);
ptr
+=
accessor
.
PointerOffset
;
return
ptr
;
}
}
}
}
}
}
}
...
...
src/Workspaces/Core/Desktop/Workspaces.Desktop.csproj
浏览文件 @
4566936c
...
@@ -95,6 +95,7 @@
...
@@ -95,6 +95,7 @@
<Compile
Include=
"Workspace\Host\Mef\DesktopMefHostServices.cs"
/>
<Compile
Include=
"Workspace\Host\Mef\DesktopMefHostServices.cs"
/>
<Compile
Include=
"Workspace\Host\Mef\MefV1HostServices.cs"
/>
<Compile
Include=
"Workspace\Host\Mef\MefV1HostServices.cs"
/>
<Compile
Include=
"Workspace\Host\SimpleAnalyzerAssemblyLoaderService.cs"
/>
<Compile
Include=
"Workspace\Host\SimpleAnalyzerAssemblyLoaderService.cs"
/>
<Compile
Include=
"Workspace\Host\TemporaryStorage\TemporaryStorageServiceFactory.CopiedMemoryMappedViewHandle.cs"
/>
<Compile
Include=
"Workspace\Host\TemporaryStorage\TemporaryStorageServiceFactory.cs"
/>
<Compile
Include=
"Workspace\Host\TemporaryStorage\TemporaryStorageServiceFactory.cs"
/>
<Compile
Include=
"Workspace\Host\TemporaryStorage\TemporaryStorageServiceFactory.MemoryMappedInfo.cs"
/>
<Compile
Include=
"Workspace\Host\TemporaryStorage\TemporaryStorageServiceFactory.MemoryMappedInfo.cs"
/>
<Compile
Include=
"Workspace\Host\TextFactory\DesktopTextFactoryService.cs"
/>
<Compile
Include=
"Workspace\Host\TextFactory\DesktopTextFactoryService.cs"
/>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录