Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
c9e06393
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,发现更多精彩内容 >>
提交
c9e06393
编写于
4月 23, 2015
作者:
P
Paul Harrington
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Redefine IStream to avoid byte[] allocation in Write
上级
9a342e59
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
84 addition
and
49 deletion
+84
-49
src/Compilers/Core/Portable/CodeAnalysis.csproj
src/Compilers/Core/Portable/CodeAnalysis.csproj
+1
-0
src/Compilers/Core/Portable/PEWriter/ComMemoryStream.cs
src/Compilers/Core/Portable/PEWriter/ComMemoryStream.cs
+52
-49
src/Compilers/Core/Portable/PEWriter/IUnsafeComStream.cs
src/Compilers/Core/Portable/PEWriter/IUnsafeComStream.cs
+31
-0
未找到文件。
src/Compilers/Core/Portable/CodeAnalysis.csproj
浏览文件 @
c9e06393
...
...
@@ -334,6 +334,7 @@
<Compile
Include=
"MetadataReference\ReferenceDirective.cs"
/>
<Compile
Include=
"MetadataReference\UnresolvedMetadataReference.cs"
/>
<Compile
Include=
"PEWriter\ComMemoryStream.cs"
/>
<Compile
Include=
"PEWriter\IUnsafeComStream.cs"
/>
<Compile
Include=
"PEWriter\MetadataHeapsBuilder.cs"
/>
<Compile
Include=
"PEWriter\ITypeReferenceExtensions.cs"
/>
<Compile
Include=
"PEWriter\NoPiaReferenceIndexer.cs"
/>
...
...
src/Compilers/Core/Portable/PEWriter/ComMemoryStream.cs
浏览文件 @
c9e06393
...
...
@@ -2,21 +2,55 @@
using
System.IO
;
using
System.Collections.Generic
;
using
System.Runtime.InteropServices.ComTypes
;
using
System.Runtime.InteropServices
;
namespace
Roslyn.Utilities
{
internal
class
ComMemoryStream
:
IStream
/// <summary>
/// A COM IStream implementation over memory. Supports just enough for DiaSymReader's PDB writing.
/// Also tuned for performance:
/// 1. SetSize (and Seek beyond the length) is very fast and doesn't re-allocate the underlying memory.
/// 2. Write is optimized to avoid copying.
/// 3. Doesn't use contiguous memory.
/// </summary>
internal
class
ComMemoryStream
:
IUnsafeComStream
{
#if DEBUG
private
const
int
ChunkSize
=
509
;
// Small prime number for debugging chunking
#else
private
const
int
ChunkSize
=
32768
;
#endif
private
List
<
byte
[
]>
_chunks
=
new
List
<
byte
[
]>
();
private
int
_position
;
private
int
_length
;
public
unsafe
void
Read
(
byte
[]
pv
,
int
cb
,
IntPtr
pcbRead
)
public
void
CopyTo
(
Stream
stream
)
{
// If the target stream allows seeking set its length upfront.
// When writing to a large file, it helps to give a hint to the OS how big the file is going to be.
if
(
stream
.
CanSeek
)
{
stream
.
SetLength
(
stream
.
Position
+
_length
);
}
int
chunkIndex
=
0
;
for
(
int
cb
=
_length
;
cb
>
0
;)
{
int
bytesToCopy
=
Math
.
Min
(
ChunkSize
,
cb
);
if
(
chunkIndex
<
_chunks
.
Count
)
{
stream
.
Write
(
_chunks
[
chunkIndex
++],
0
,
bytesToCopy
);
}
else
{
// Fill remaining space with zero bytes
for
(
int
i
=
0
;
i
<
bytesToCopy
;
i
++)
{
stream
.
WriteByte
(
0
);
}
}
cb
-=
bytesToCopy
;
}
}
unsafe
void
IUnsafeComStream
.
Read
(
byte
[]
pv
,
int
cb
,
IntPtr
pcbRead
)
{
int
chunkIndex
=
_position
/
ChunkSize
;
int
chunkOffset
=
_position
%
ChunkSize
;
...
...
@@ -76,7 +110,7 @@ private int SetPosition(int newPos)
return
newPos
;
}
public
unsafe
void
Seek
(
long
dlibMove
,
int
origin
,
IntPtr
plibNewPosition
)
unsafe
void
IUnsafeComStream
.
Seek
(
long
dlibMove
,
int
origin
,
IntPtr
plibNewPosition
)
{
int
newPosition
;
...
...
@@ -104,12 +138,12 @@ public unsafe void Seek(long dlibMove, int origin, IntPtr plibNewPosition)
}
}
public
void
SetSize
(
long
libNewSize
)
void
IUnsafeComStream
.
SetSize
(
long
libNewSize
)
{
_length
=
(
int
)
libNewSize
;
}
public
void
Stat
(
out
STATSTG
pstatstg
,
int
grfStatFlag
)
void
IUnsafeComStream
.
Stat
(
out
STATSTG
pstatstg
,
int
grfStatFlag
)
{
pstatstg
=
new
STATSTG
()
{
...
...
@@ -117,7 +151,7 @@ public void Stat(out STATSTG pstatstg, int grfStatFlag)
};
}
public
unsafe
void
Write
(
byte
[]
pv
,
int
cb
,
IntPtr
pcbWritten
)
unsafe
void
IUnsafeComStream
.
Write
(
IntPtr
pv
,
int
cb
,
IntPtr
pcbWritten
)
{
int
chunkIndex
=
_position
/
ChunkSize
;
int
chunkOffset
=
_position
%
ChunkSize
;
...
...
@@ -135,7 +169,7 @@ public unsafe void Write(byte[] pv, int cb, IntPtr pcbWritten)
_chunks
.
Add
(
new
byte
[
ChunkSize
]);
}
Array
.
Copy
(
pv
,
bytesWritten
,
_chunks
[
chunkIndex
],
chunkOffset
,
bytesToCopy
);
Marshal
.
Copy
(
pv
+
bytesWritten
,
_chunks
[
chunkIndex
],
chunkOffset
,
bytesToCopy
);
bytesWritten
+=
bytesToCopy
;
_position
+=
bytesToCopy
;
cb
-=
bytesToCopy
;
...
...
@@ -159,65 +193,34 @@ public unsafe void Write(byte[] pv, int cb, IntPtr pcbWritten)
}
}
public
void
CopyTo
(
Stream
stream
)
{
int
size
=
_length
;
// If the target stream allows seeking set its length upfront.
// When writing to a large file, it helps to give a hint to the OS how big the file is going to be.
if
(
stream
.
CanSeek
)
{
stream
.
SetLength
(
stream
.
Position
+
size
);
}
int
chunkIndex
=
0
;
for
(
int
cb
=
size
;
cb
>
0
;)
{
int
bytesToCopy
=
Math
.
Min
(
ChunkSize
,
cb
);
if
(
chunkIndex
<
_chunks
.
Count
)
{
stream
.
Write
(
_chunks
[
chunkIndex
++],
0
,
bytesToCopy
);
}
else
{
// Fill remaining space with zero bytes
for
(
int
i
=
0
;
i
<
bytesToCopy
;
i
++)
{
stream
.
WriteByte
(
0
);
}
}
cb
-=
bytesToCopy
;
}
}
public
void
Commit
(
int
grfCommitFlags
)
void
IUnsafeComStream
.
Commit
(
int
grfCommitFlags
)
{
}
public
void
Clone
(
out
IStream
ppstm
)
void
IUnsafeComStream
.
Clone
(
out
IStream
ppstm
)
{
throw
new
NotSupportedException
();
}
public
void
CopyTo
(
IStream
pstm
,
long
cb
,
IntPtr
pcbRead
,
IntPtr
pcbWritten
)
void
IUnsafeComStream
.
CopyTo
(
IStream
pstm
,
long
cb
,
IntPtr
pcbRead
,
IntPtr
pcbWritten
)
{
throw
new
NotSupportedException
();
}
public
void
LockRegion
(
long
libOffset
,
long
cb
,
int
lockType
)
void
IUnsafeComStream
.
LockRegion
(
long
libOffset
,
long
cb
,
int
lockType
)
{
throw
new
NotSupportedException
();
}
public
void
Revert
()
void
IUnsafeComStream
.
Revert
()
{
throw
new
NotSupportedException
();
}
public
void
UnlockRegion
(
long
libOffset
,
long
cb
,
int
lockType
)
void
IUnsafeComStream
.
UnlockRegion
(
long
libOffset
,
long
cb
,
int
lockType
)
{
throw
new
NotSupportedException
();
}
}
}
src/Compilers/Core/Portable/PEWriter/IUnsafeComStream.cs
0 → 100644
浏览文件 @
c9e06393
using
System
;
using
System.Runtime.InteropServices
;
using
System.Runtime.InteropServices.ComTypes
;
namespace
Roslyn.Utilities
{
/// <summary>
/// This is a re-definition of COM's IStream interface. The important change is that
/// the Write method takes an <see cref="IntPtr"/> instead of a byte[] to avoid the
/// allocation cost when called from native code.
/// </summary>
[
Guid
(
"0000000c-0000-0000-C000-000000000046"
),
InterfaceType
(
ComInterfaceType
.
InterfaceIsIUnknown
),
ComImport
]
internal
interface
IUnsafeComStream
{
// ISequentialStream portion
void
Read
([
MarshalAs
(
UnmanagedType
.
LPArray
,
SizeParamIndex
=
1
),
Out
]
byte
[]
pv
,
int
cb
,
IntPtr
pcbRead
);
void
Write
(
IntPtr
pv
,
int
cb
,
IntPtr
pcbWritten
);
// IStream portion
void
Seek
(
long
dlibMove
,
int
dwOrigin
,
IntPtr
plibNewPosition
);
void
SetSize
(
long
libNewSize
);
void
CopyTo
(
IStream
pstm
,
long
cb
,
IntPtr
pcbRead
,
IntPtr
pcbWritten
);
void
Commit
(
int
grfCommitFlags
);
void
Revert
();
void
LockRegion
(
long
libOffset
,
long
cb
,
int
dwLockType
);
void
UnlockRegion
(
long
libOffset
,
long
cb
,
int
dwLockType
);
void
Stat
(
out
STATSTG
pstatstg
,
int
grfStatFlag
);
void
Clone
(
out
IStream
ppstm
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录