Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
a404917e
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,发现更多精彩内容 >>
提交
a404917e
编写于
5月 10, 2017
作者:
C
CyrusNajmabadi
提交者:
GitHub
5月 10, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #19374 from CyrusNajmabadi/serializationSimplification
Simplify serialization.
上级
5e053aaf
969b5cb1
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
68 addition
and
59 deletion
+68
-59
src/Compilers/Core/Portable/Serialization/IObjectWritable.cs
src/Compilers/Core/Portable/Serialization/IObjectWritable.cs
+1
-1
src/Compilers/Core/Portable/Serialization/ObjectBinder.cs
src/Compilers/Core/Portable/Serialization/ObjectBinder.cs
+0
-2
src/Compilers/Core/Portable/Serialization/ObjectReader.cs
src/Compilers/Core/Portable/Serialization/ObjectReader.cs
+31
-33
src/Compilers/Core/Portable/Serialization/ObjectWriter.cs
src/Compilers/Core/Portable/Serialization/ObjectWriter.cs
+36
-23
未找到文件。
src/Compilers/Core/Portable/Serialization/IObjectWritable.cs
浏览文件 @
a404917e
...
...
@@ -10,4 +10,4 @@ internal interface IObjectWritable
{
void
WriteTo
(
ObjectWriter
writer
);
}
}
}
\ No newline at end of file
src/Compilers/Core/Portable/Serialization/ObjectBinder.cs
浏览文件 @
a404917e
...
...
@@ -2,8 +2,6 @@
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Linq
;
namespace
Roslyn.Utilities
{
...
...
src/Compilers/Core/Portable/Serialization/ObjectReader.cs
浏览文件 @
a404917e
...
...
@@ -2,10 +2,8 @@
using
System
;
using
System.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
System.IO
;
using
System.Runtime.CompilerServices
;
using
System.Text
;
using
System.Threading
;
using
System.Threading.Tasks
;
...
...
@@ -32,16 +30,18 @@ internal sealed partial class ObjectReader : IDisposable
/// this version, just change VersionByte2.
/// </summary>
internal
const
byte
VersionByte1
=
0
b10101010
;
internal
const
byte
VersionByte2
=
0
b0000
0111
;
internal
const
byte
VersionByte2
=
0
b0000
1000
;
private
readonly
BinaryReader
_reader
;
private
readonly
CancellationToken
_cancellationToken
;
/// <summary>
/// Map of reference id's to deserialized objects.
///
/// These are not readonly because they're structs and we mutate them.
/// </summary>
private
readonly
ReaderReferenceMap
<
object
>
_objectReferenceMap
;
private
readonly
ReaderReferenceMap
<
string
>
_stringReferenceMap
;
private
ReaderReferenceMap
<
object
>
_objectReferenceMap
;
private
ReaderReferenceMap
<
string
>
_stringReferenceMap
;
/// <summary>
/// Copy of the global binder data that maps from Types to the appropriate reading-function
...
...
@@ -67,8 +67,8 @@ internal sealed partial class ObjectReader : IDisposable
Debug
.
Assert
(
BitConverter
.
IsLittleEndian
);
_reader
=
new
BinaryReader
(
stream
,
Encoding
.
UTF8
);
_objectReferenceMap
=
new
ReaderReferenceMap
<
object
>
();
_stringReferenceMap
=
new
ReaderReferenceMap
<
string
>
();
_objectReferenceMap
=
ReaderReferenceMap
<
object
>.
Create
();
_stringReferenceMap
=
ReaderReferenceMap
<
string
>.
Create
();
// Capture a copy of the current static binder state. That way we don't have to
// access any locks while we're doing our processing.
...
...
@@ -227,17 +227,18 @@ private object ReadValueWorker()
/// <summary>
/// An reference-id to object map, that can share base data efficiently.
/// </summary>
private
class
ReaderReferenceMap
<
T
>
where
T
:
class
private
struct
ReaderReferenceMap
<
T
>
where
T
:
class
{
private
readonly
List
<
T
>
_values
;
internal
static
readonly
ObjectPool
<
List
<
T
>>
s_objectListPool
=
new
ObjectPool
<
List
<
T
>>(()
=>
new
List
<
T
>(
20
));
public
ReaderReferenceMap
()
{
_values
=
s_objectListPool
.
Allocate
();
}
private
ReaderReferenceMap
(
List
<
T
>
values
)
=>
_values
=
values
;
public
static
ReaderReferenceMap
<
T
>
Create
()
=>
new
ReaderReferenceMap
<
T
>(
s_objectListPool
.
Allocate
());
public
void
Dispose
()
{
...
...
@@ -245,21 +246,22 @@ public void Dispose()
s_objectListPool
.
Free
(
_values
);
}
public
int
GetNextReferenceId
()
public
int
GetNextObjectId
()
{
var
id
=
_values
.
Count
;
_values
.
Add
(
null
);
return
_values
.
Count
-
1
;
return
id
;
}
public
void
SetValue
(
int
referenceId
,
T
value
)
{
_values
[
referenceId
]
=
value
;
}
public
void
AddValue
(
T
value
)
=>
_values
.
Add
(
value
);
public
void
AddValue
(
int
index
,
T
value
)
=>
_values
[
index
]
=
value
;
public
T
GetValue
(
int
referenceId
)
{
return
_values
[
referenceId
];
}
=>
_values
[
referenceId
];
}
internal
uint
ReadCompressedUInt
()
...
...
@@ -321,7 +323,6 @@ private string ReadStringValue(EncodingKind kind)
private
unsafe
string
ReadStringLiteral
(
EncodingKind
kind
)
{
int
id
=
_stringReferenceMap
.
GetNextReferenceId
();
string
value
;
if
(
kind
==
EncodingKind
.
StringUtf8
)
{
...
...
@@ -338,7 +339,7 @@ private unsafe string ReadStringLiteral(EncodingKind kind)
}
}
_stringReferenceMap
.
SetValue
(
id
,
value
);
_stringReferenceMap
.
AddValue
(
value
);
return
value
;
}
...
...
@@ -576,21 +577,18 @@ public Type ReadType()
private
Type
ReadTypeAfterTag
()
=>
_binderSnapshot
.
GetTypeFromId
(
this
.
ReadInt32
());
private
Func
<
ObjectReader
,
object
>
ReadTypeReader
()
{
_reader
.
ReadByte
();
return
_binderSnapshot
.
GetTypeReaderFromId
(
this
.
ReadInt32
());
}
private
object
ReadObject
()
{
var
id
=
_objectReferenceMap
.
GetNextReferenceId
();
var
objectId
=
_objectReferenceMap
.
GetNextObjectId
();
// reading an object may recurse. So we need to grab our ID up front as we'll
// end up making our sub-objects before we make this object.
var
typeReader
=
this
.
ReadTypeReader
(
);
var
typeReader
=
_binderSnapshot
.
GetTypeReaderFromId
(
this
.
ReadInt32
()
);
// recursive: read and construct instance immediately from member elements encoding next in the stream
var
instance
=
typeReader
(
this
);
_objectReferenceMap
.
SetValue
(
i
d
,
instance
);
_objectReferenceMap
.
AddValue
(
objectI
d
,
instance
);
return
instance
;
}
...
...
@@ -609,4 +607,4 @@ private static Exception NoSerializationReaderException(string typeName)
return
new
InvalidOperationException
(
string
.
Format
(
Resources
.
Cannot_serialize_type_0
,
typeName
));
}
}
}
}
\ No newline at end of file
src/Compilers/Core/Portable/Serialization/ObjectWriter.cs
浏览文件 @
a404917e
...
...
@@ -32,9 +32,26 @@ internal sealed partial class ObjectWriter : IDisposable
/// Map of serialized object's reference ids. The object-reference-map uses reference equality
/// for performance. While the string-reference-map uses value-equality for greater cache hits
/// and reuse.
///
/// These are not readonly because they're structs and we mutate them.
///
/// When we write out objects/strings we give each successive, unique, item a monotonically
/// increasing integral ID starting at 0. I.e. the first object gets ID-0, the next gets
/// ID-1 and so on and so forth. We do *not* include these IDs with the object when it is
/// written out. We only include the ID if we hit the object *again* while writing.
///
/// During reading, the reader knows to give each object it reads the same monotonically
/// increasing integral value. i.e. the first object it reads is put into an array at position
/// 0, the next at position 1, and so on. Then, when the reader reads in an object-reference
/// it can just retrieved it directly from that array.
///
/// In other words, writing and reading take advantage of the fact that they know they will
/// write and read objects in the exact same order. So they only need the IDs for references
/// and not the objects themselves because the ID is inferred from the order the object is
/// written or read in.
/// </summary>
private
readonly
WriterReferenceMap
_objectReferenceMap
;
private
readonly
WriterReferenceMap
_stringReferenceMap
;
private
WriterReferenceMap
_objectReferenceMap
;
private
WriterReferenceMap
_stringReferenceMap
;
/// <summary>
/// Copy of the global binder data that maps from Types to the appropriate reading-function
...
...
@@ -279,7 +296,7 @@ private void WriteEncodedUInt32(uint v)
/// <summary>
/// An object reference to reference-id map, that can share base data efficiently.
/// </summary>
private
class
WriterReferenceMap
private
struct
WriterReferenceMap
{
private
readonly
Dictionary
<
object
,
int
>
_valueToIdMap
;
private
readonly
bool
_valueEquality
;
...
...
@@ -294,16 +311,16 @@ private class WriterReferenceMap
public
WriterReferenceMap
(
bool
valueEquality
)
{
_valueEquality
=
valueEquality
;
_valueToIdMap
=
GetDictionaryPool
().
Allocate
();
_valueToIdMap
=
GetDictionaryPool
(
valueEquality
).
Allocate
();
_nextId
=
0
;
}
private
ObjectPool
<
Dictionary
<
object
,
int
>>
GetDictionaryPool
(
)
=>
_
valueEquality
?
s_valueDictionaryPool
:
s_referenceDictionaryPool
;
private
static
ObjectPool
<
Dictionary
<
object
,
int
>>
GetDictionaryPool
(
bool
valueEquality
)
=>
valueEquality
?
s_valueDictionaryPool
:
s_referenceDictionaryPool
;
public
void
Dispose
()
{
var
pool
=
GetDictionaryPool
();
var
pool
=
GetDictionaryPool
(
_valueEquality
);
// If the map grew too big, don't return it to the pool.
// When testing with the Roslyn solution, this dropped only 2.5% of requests.
...
...
@@ -319,15 +336,12 @@ public void Dispose()
}
public
bool
TryGetReferenceId
(
object
value
,
out
int
referenceId
)
{
return
_valueToIdMap
.
TryGetValue
(
value
,
out
referenceId
);
}
=>
_valueToIdMap
.
TryGetValue
(
value
,
out
referenceId
);
public
int
Add
(
object
value
)
public
void
Add
(
object
value
)
{
var
id
=
_nextId
++;
_valueToIdMap
.
Add
(
value
,
id
);
return
id
;
}
}
...
...
@@ -728,7 +742,8 @@ private void WriteObject(object instance, IObjectWritable instanceAsWritableOpt)
// don't blow the stack. 'LongRunning' ensures that we get a dedicated thread
// to do this work. That way we don't end up blocking the threadpool.
var
task
=
Task
.
Factory
.
StartNew
(
()
=>
WriteObjectWorker
(
instance
,
writable
),
obj
=>
WriteObjectWorker
((
IObjectWritable
)
obj
),
writable
,
_cancellationToken
,
TaskCreationOptions
.
LongRunning
,
TaskScheduler
.
Default
);
...
...
@@ -736,7 +751,7 @@ private void WriteObject(object instance, IObjectWritable instanceAsWritableOpt)
}
else
{
WriteObjectWorker
(
instance
,
writable
);
WriteObjectWorker
(
writable
);
}
_recursionDepth
--;
...
...
@@ -744,19 +759,17 @@ private void WriteObject(object instance, IObjectWritable instanceAsWritableOpt)
}
}
private
void
WriteObjectWorker
(
object
instance
,
IObjectWritable
writable
)
private
void
WriteObjectWorker
(
IObjectWritable
writable
)
{
// emit object header up front
this
.
WriteObjectHeader
(
instance
,
0
);
writable
.
WriteTo
(
this
);
}
private
void
WriteObjectHeader
(
object
instance
,
uint
memberCount
)
{
_objectReferenceMap
.
Add
(
instance
);
_objectReferenceMap
.
Add
(
writable
);
_writer
.
Write
((
byte
)
EncodingKind
.
Object
);
this
.
WriteKnownType
(
instance
.
GetType
());
// Directly write out the type-id for this object. i.e. no need to write out the 'Type'
// tag since we just wrote out the 'Object' tag
this
.
WriteInt32
(
_binderSnapshot
.
GetTypeId
(
writable
.
GetType
()));
writable
.
WriteTo
(
this
);
}
private
static
Exception
NoSerializationTypeException
(
string
typeName
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录