Skip to content

Commit 76625cc

Browse files
committed
Make fast path when the writer has enough buffer.
This commit also enable unsafe option for future use.
1 parent 785882c commit 76625cc

5 files changed

Lines changed: 213 additions & 51 deletions

File tree

src/MsgPack.Unity.Full/MsgPack.Unity.Full.csproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<WarningLevel>4</WarningLevel>
2323
<DocumentationFile>bin\Debug\MsgPack.XML</DocumentationFile>
2424
<NoWarn>3001,3002</NoWarn>
25+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
2526
</PropertyGroup>
2627
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
2728
<DebugType>pdbonly</DebugType>
@@ -32,18 +33,21 @@
3233
<WarningLevel>4</WarningLevel>
3334
<DocumentationFile>..\..\build\MsgPack-CLI\unity-full\MsgPack.XML</DocumentationFile>
3435
<NoWarn>3001,3002</NoWarn>
36+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
3537
</PropertyGroup>
3638
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU'">
3739
<OutputPath>bin\CodeAnalysis\</OutputPath>
3840
<DefineConstants>TRACE;UNITY_IPHONE;MSGPACK_UNITY_FULL;AOT;CODE_ANALYSIS</DefineConstants>
39-
<DocumentationFile></DocumentationFile>
41+
<DocumentationFile>
42+
</DocumentationFile>
4043
<Optimize>true</Optimize>
4144
<NoWarn>3001,3002</NoWarn>
4245
<DebugType>pdbonly</DebugType>
4346
<PlatformTarget>AnyCPU</PlatformTarget>
4447
<ErrorReport>prompt</ErrorReport>
4548
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
4649
<RunCodeAnalysis>true</RunCodeAnalysis>
50+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
4751
</PropertyGroup>
4852
<ItemGroup>
4953
<Compile Include="..\CommonAssemblyInfo.cs">

src/MsgPack.Unity/MsgPack.Unity.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<DocumentationFile>bin\Debug\MsgPack.XML</DocumentationFile>
2626
<NoWarn>3001,3002</NoWarn>
2727
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
28+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
2829
</PropertyGroup>
2930
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
3031
<DebugType>pdbonly</DebugType>
@@ -36,6 +37,7 @@
3637
<DocumentationFile>..\..\build\MsgPack-CLI\unity\MsgPack.XML</DocumentationFile>
3738
<NoWarn>3001,3002</NoWarn>
3839
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
40+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
3941
</PropertyGroup>
4042
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'CodeAnalysis|AnyCPU'">
4143
<OutputPath>bin\CodeAnalysis\</OutputPath>
@@ -48,6 +50,7 @@
4850
<ErrorReport>prompt</ErrorReport>
4951
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
5052
<RunCodeAnalysis>true</RunCodeAnalysis>
53+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
5154
</PropertyGroup>
5255
<ItemGroup>
5356
<Compile Include="..\CommonAssemblyInfo.cs">

src/MsgPack.Uwp/MsgPack.Uwp.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
<DefineConstants>TRACE;DEBUG;NETFX_CORE;WINDOWS_UWP;AOT;NETSTANDARD1_3;FEATURE_TAP;FEATURE_CONCURRENT</DefineConstants>
2727
<ErrorReport>prompt</ErrorReport>
2828
<WarningLevel>4</WarningLevel>
29+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
2930
</PropertyGroup>
3031
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
3132
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -36,6 +37,7 @@
3637
<ErrorReport>prompt</ErrorReport>
3738
<WarningLevel>4</WarningLevel>
3839
<DocumentationFile>..\..\bin\uap10\MsgPack.XML</DocumentationFile>
40+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
3941
</PropertyGroup>
4042
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
4143
<PlatformTarget>x86</PlatformTarget>
@@ -969,6 +971,7 @@
969971
<UseVSHostingProcess>false</UseVSHostingProcess>
970972
<ErrorReport>prompt</ErrorReport>
971973
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
974+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
972975
</PropertyGroup>
973976
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'CodeAnalysis|x86'">
974977
<OutputPath>bin\x86\CodeAnalysis\</OutputPath>

src/MsgPack/ByteArrayPackerWriter.TypedWrite.cs

Lines changed: 144 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,26 @@ public override void WriteBytes( byte header, byte value )
5555

5656
currentBuffer[ currentBufferOffset ] = header;
5757
currentBufferOffset += 1;
58-
58+
59+
if ( currentBufferLimit - currentBufferOffset >= sizeof( byte ) )
60+
{
61+
// Fast path
62+
currentBuffer[ currentBufferOffset ] = unchecked( ( byte )( value >> ( ( sizeof( byte ) - 1 ) * 8 ) & 0xFF ) );
63+
currentBufferOffset += sizeof( byte );
64+
}
65+
else
66+
{
67+
this.WriteBytesSlow( value, ref currentBufferIndex, ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit );
68+
}
69+
70+
this._currentBufferIndex = currentBufferIndex;
71+
this._currentBuffer = currentBuffer;
72+
this._currentBufferOffset = currentBufferOffset;
73+
this._currentBufferLimit = currentBufferLimit;
74+
}
75+
76+
private void WriteBytesSlow( byte value, ref int currentBufferIndex, ref byte[] currentBuffer, ref int currentBufferOffset, ref int currentBufferLimit )
77+
{
5978
if ( !this.ShiftBufferIfNeeded( sizeof( byte ), ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit, ref currentBufferIndex ) )
6079
{
6180
this.ThrowEofException( sizeof( byte ) );
@@ -80,11 +99,6 @@ public override void WriteBytes( byte header, byte value )
8099

81100
bufferRemaining = currentBufferLimit - currentBufferOffset;
82101
}
83-
84-
this._currentBufferIndex = currentBufferIndex;
85-
this._currentBuffer = currentBuffer;
86-
this._currentBufferOffset = currentBufferOffset;
87-
this._currentBufferLimit = currentBufferLimit;
88102
}
89103

90104
public override void WriteBytes( byte header, ushort value )
@@ -100,7 +114,27 @@ public override void WriteBytes( byte header, ushort value )
100114

101115
currentBuffer[ currentBufferOffset ] = header;
102116
currentBufferOffset += 1;
103-
117+
118+
if ( currentBufferLimit - currentBufferOffset >= sizeof( ushort ) )
119+
{
120+
// Fast path
121+
currentBuffer[ currentBufferOffset ] = unchecked( ( byte )( value >> ( ( sizeof( ushort ) - 1 ) * 8 ) & 0xFF ) );
122+
currentBuffer[ currentBufferOffset + 1 ] = unchecked( ( byte )( value >> ( ( sizeof( ushort ) - 2 ) * 8 ) & 0xFF ) );
123+
currentBufferOffset += sizeof( ushort );
124+
}
125+
else
126+
{
127+
this.WriteBytesSlow( value, ref currentBufferIndex, ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit );
128+
}
129+
130+
this._currentBufferIndex = currentBufferIndex;
131+
this._currentBuffer = currentBuffer;
132+
this._currentBufferOffset = currentBufferOffset;
133+
this._currentBufferLimit = currentBufferLimit;
134+
}
135+
136+
private void WriteBytesSlow( ushort value, ref int currentBufferIndex, ref byte[] currentBuffer, ref int currentBufferOffset, ref int currentBufferLimit )
137+
{
104138
if ( !this.ShiftBufferIfNeeded( sizeof( ushort ), ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit, ref currentBufferIndex ) )
105139
{
106140
this.ThrowEofException( sizeof( ushort ) );
@@ -125,11 +159,6 @@ public override void WriteBytes( byte header, ushort value )
125159

126160
bufferRemaining = currentBufferLimit - currentBufferOffset;
127161
}
128-
129-
this._currentBufferIndex = currentBufferIndex;
130-
this._currentBuffer = currentBuffer;
131-
this._currentBufferOffset = currentBufferOffset;
132-
this._currentBufferLimit = currentBufferLimit;
133162
}
134163

135164
public override void WriteBytes( byte header, uint value )
@@ -145,7 +174,29 @@ public override void WriteBytes( byte header, uint value )
145174

146175
currentBuffer[ currentBufferOffset ] = header;
147176
currentBufferOffset += 1;
148-
177+
178+
if ( currentBufferLimit - currentBufferOffset >= sizeof( uint ) )
179+
{
180+
// Fast path
181+
currentBuffer[ currentBufferOffset ] = unchecked( ( byte )( value >> ( ( sizeof( uint ) - 1 ) * 8 ) & 0xFF ) );
182+
currentBuffer[ currentBufferOffset + 1 ] = unchecked( ( byte )( value >> ( ( sizeof( uint ) - 2 ) * 8 ) & 0xFF ) );
183+
currentBuffer[ currentBufferOffset + 2 ] = unchecked( ( byte )( value >> ( ( sizeof( uint ) - 3 ) * 8 ) & 0xFF ) );
184+
currentBuffer[ currentBufferOffset + 3 ] = unchecked( ( byte )( value >> ( ( sizeof( uint ) - 4 ) * 8 ) & 0xFF ) );
185+
currentBufferOffset += sizeof( uint );
186+
}
187+
else
188+
{
189+
this.WriteBytesSlow( value, ref currentBufferIndex, ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit );
190+
}
191+
192+
this._currentBufferIndex = currentBufferIndex;
193+
this._currentBuffer = currentBuffer;
194+
this._currentBufferOffset = currentBufferOffset;
195+
this._currentBufferLimit = currentBufferLimit;
196+
}
197+
198+
private void WriteBytesSlow( uint value, ref int currentBufferIndex, ref byte[] currentBuffer, ref int currentBufferOffset, ref int currentBufferLimit )
199+
{
149200
if ( !this.ShiftBufferIfNeeded( sizeof( uint ), ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit, ref currentBufferIndex ) )
150201
{
151202
this.ThrowEofException( sizeof( uint ) );
@@ -170,11 +221,6 @@ public override void WriteBytes( byte header, uint value )
170221

171222
bufferRemaining = currentBufferLimit - currentBufferOffset;
172223
}
173-
174-
this._currentBufferIndex = currentBufferIndex;
175-
this._currentBuffer = currentBuffer;
176-
this._currentBufferOffset = currentBufferOffset;
177-
this._currentBufferLimit = currentBufferLimit;
178224
}
179225

180226
public override void WriteBytes( byte header, ulong value )
@@ -190,7 +236,33 @@ public override void WriteBytes( byte header, ulong value )
190236

191237
currentBuffer[ currentBufferOffset ] = header;
192238
currentBufferOffset += 1;
193-
239+
240+
if ( currentBufferLimit - currentBufferOffset >= sizeof( ulong ) )
241+
{
242+
// Fast path
243+
currentBuffer[ currentBufferOffset ] = unchecked( ( byte )( value >> ( ( sizeof( ulong ) - 1 ) * 8 ) & 0xFF ) );
244+
currentBuffer[ currentBufferOffset + 1 ] = unchecked( ( byte )( value >> ( ( sizeof( ulong ) - 2 ) * 8 ) & 0xFF ) );
245+
currentBuffer[ currentBufferOffset + 2 ] = unchecked( ( byte )( value >> ( ( sizeof( ulong ) - 3 ) * 8 ) & 0xFF ) );
246+
currentBuffer[ currentBufferOffset + 3 ] = unchecked( ( byte )( value >> ( ( sizeof( ulong ) - 4 ) * 8 ) & 0xFF ) );
247+
currentBuffer[ currentBufferOffset + 4 ] = unchecked( ( byte )( value >> ( ( sizeof( ulong ) - 5 ) * 8 ) & 0xFF ) );
248+
currentBuffer[ currentBufferOffset + 5 ] = unchecked( ( byte )( value >> ( ( sizeof( ulong ) - 6 ) * 8 ) & 0xFF ) );
249+
currentBuffer[ currentBufferOffset + 6 ] = unchecked( ( byte )( value >> ( ( sizeof( ulong ) - 7 ) * 8 ) & 0xFF ) );
250+
currentBuffer[ currentBufferOffset + 7 ] = unchecked( ( byte )( value >> ( ( sizeof( ulong ) - 8 ) * 8 ) & 0xFF ) );
251+
currentBufferOffset += sizeof( ulong );
252+
}
253+
else
254+
{
255+
this.WriteBytesSlow( value, ref currentBufferIndex, ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit );
256+
}
257+
258+
this._currentBufferIndex = currentBufferIndex;
259+
this._currentBuffer = currentBuffer;
260+
this._currentBufferOffset = currentBufferOffset;
261+
this._currentBufferLimit = currentBufferLimit;
262+
}
263+
264+
private void WriteBytesSlow( ulong value, ref int currentBufferIndex, ref byte[] currentBuffer, ref int currentBufferOffset, ref int currentBufferLimit )
265+
{
194266
if ( !this.ShiftBufferIfNeeded( sizeof( ulong ), ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit, ref currentBufferIndex ) )
195267
{
196268
this.ThrowEofException( sizeof( ulong ) );
@@ -215,11 +287,6 @@ public override void WriteBytes( byte header, ulong value )
215287

216288
bufferRemaining = currentBufferLimit - currentBufferOffset;
217289
}
218-
219-
this._currentBufferIndex = currentBufferIndex;
220-
this._currentBuffer = currentBuffer;
221-
this._currentBufferOffset = currentBufferOffset;
222-
this._currentBufferLimit = currentBufferLimit;
223290
}
224291

225292
public override void WriteBytes( byte header, float value )
@@ -236,7 +303,29 @@ public override void WriteBytes( byte header, float value )
236303

237304
currentBuffer[ currentBufferOffset ] = header;
238305
currentBufferOffset += 1;
239-
306+
307+
if ( currentBufferLimit - currentBufferOffset >= sizeof( float ) )
308+
{
309+
// Fast path
310+
currentBuffer[ currentBufferOffset ] = unchecked( ( byte )( bits >> ( ( sizeof( float ) - 1 ) * 8 ) & 0xFF ) );
311+
currentBuffer[ currentBufferOffset + 1 ] = unchecked( ( byte )( bits >> ( ( sizeof( float ) - 2 ) * 8 ) & 0xFF ) );
312+
currentBuffer[ currentBufferOffset + 2 ] = unchecked( ( byte )( bits >> ( ( sizeof( float ) - 3 ) * 8 ) & 0xFF ) );
313+
currentBuffer[ currentBufferOffset + 3 ] = unchecked( ( byte )( bits >> ( ( sizeof( float ) - 4 ) * 8 ) & 0xFF ) );
314+
currentBufferOffset += sizeof( float );
315+
}
316+
else
317+
{
318+
this.WriteBytesSlow( bits, ref currentBufferIndex, ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit );
319+
}
320+
321+
this._currentBufferIndex = currentBufferIndex;
322+
this._currentBuffer = currentBuffer;
323+
this._currentBufferOffset = currentBufferOffset;
324+
this._currentBufferLimit = currentBufferLimit;
325+
}
326+
327+
private void WriteBytesSlow( int value, ref int currentBufferIndex, ref byte[] currentBuffer, ref int currentBufferOffset, ref int currentBufferLimit )
328+
{
240329
if ( !this.ShiftBufferIfNeeded( sizeof( float ), ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit, ref currentBufferIndex ) )
241330
{
242331
this.ThrowEofException( sizeof( float ) );
@@ -249,7 +338,7 @@ public override void WriteBytes( byte header, float value )
249338
var currentWritten = 0;
250339
for ( ; currentWritten < bufferRemaining && totalWritten < sizeof( float ); currentWritten++, totalWritten++ )
251340
{
252-
currentBuffer[ currentBufferOffset + currentWritten ] = unchecked( ( byte )( bits >> ( ( sizeof( float ) - totalWritten - 1 ) * 8 ) & 0xFF ) );
341+
currentBuffer[ currentBufferOffset + currentWritten ] = unchecked( ( byte )( value >> ( ( sizeof( float ) - totalWritten - 1 ) * 8 ) & 0xFF ) );
253342
}
254343

255344
currentBufferOffset += currentWritten;
@@ -261,11 +350,6 @@ public override void WriteBytes( byte header, float value )
261350

262351
bufferRemaining = currentBufferLimit - currentBufferOffset;
263352
}
264-
265-
this._currentBufferIndex = currentBufferIndex;
266-
this._currentBuffer = currentBuffer;
267-
this._currentBufferOffset = currentBufferOffset;
268-
this._currentBufferLimit = currentBufferLimit;
269353
}
270354

271355
public override void WriteBytes( byte header, double value )
@@ -282,7 +366,33 @@ public override void WriteBytes( byte header, double value )
282366

283367
currentBuffer[ currentBufferOffset ] = header;
284368
currentBufferOffset += 1;
285-
369+
370+
if ( currentBufferLimit - currentBufferOffset >= sizeof( double ) )
371+
{
372+
// Fast path
373+
currentBuffer[ currentBufferOffset ] = unchecked( ( byte )( bits >> ( ( sizeof( double ) - 1 ) * 8 ) & 0xFF ) );
374+
currentBuffer[ currentBufferOffset + 1 ] = unchecked( ( byte )( bits >> ( ( sizeof( double ) - 2 ) * 8 ) & 0xFF ) );
375+
currentBuffer[ currentBufferOffset + 2 ] = unchecked( ( byte )( bits >> ( ( sizeof( double ) - 3 ) * 8 ) & 0xFF ) );
376+
currentBuffer[ currentBufferOffset + 3 ] = unchecked( ( byte )( bits >> ( ( sizeof( double ) - 4 ) * 8 ) & 0xFF ) );
377+
currentBuffer[ currentBufferOffset + 4 ] = unchecked( ( byte )( bits >> ( ( sizeof( double ) - 5 ) * 8 ) & 0xFF ) );
378+
currentBuffer[ currentBufferOffset + 5 ] = unchecked( ( byte )( bits >> ( ( sizeof( double ) - 6 ) * 8 ) & 0xFF ) );
379+
currentBuffer[ currentBufferOffset + 6 ] = unchecked( ( byte )( bits >> ( ( sizeof( double ) - 7 ) * 8 ) & 0xFF ) );
380+
currentBuffer[ currentBufferOffset + 7 ] = unchecked( ( byte )( bits >> ( ( sizeof( double ) - 8 ) * 8 ) & 0xFF ) );
381+
currentBufferOffset += sizeof( double );
382+
}
383+
else
384+
{
385+
this.WriteBytesSlow( bits, ref currentBufferIndex, ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit );
386+
}
387+
388+
this._currentBufferIndex = currentBufferIndex;
389+
this._currentBuffer = currentBuffer;
390+
this._currentBufferOffset = currentBufferOffset;
391+
this._currentBufferLimit = currentBufferLimit;
392+
}
393+
394+
private void WriteBytesSlow( long value, ref int currentBufferIndex, ref byte[] currentBuffer, ref int currentBufferOffset, ref int currentBufferLimit )
395+
{
286396
if ( !this.ShiftBufferIfNeeded( sizeof( double ), ref currentBuffer, ref currentBufferOffset, ref currentBufferLimit, ref currentBufferIndex ) )
287397
{
288398
this.ThrowEofException( sizeof( double ) );
@@ -295,7 +405,7 @@ public override void WriteBytes( byte header, double value )
295405
var currentWritten = 0;
296406
for ( ; currentWritten < bufferRemaining && totalWritten < sizeof( double ); currentWritten++, totalWritten++ )
297407
{
298-
currentBuffer[ currentBufferOffset + currentWritten ] = unchecked( ( byte )( bits >> ( ( sizeof( double ) - totalWritten - 1 ) * 8 ) & 0xFF ) );
408+
currentBuffer[ currentBufferOffset + currentWritten ] = unchecked( ( byte )( value >> ( ( sizeof( double ) - totalWritten - 1 ) * 8 ) & 0xFF ) );
299409
}
300410

301411
currentBufferOffset += currentWritten;
@@ -307,11 +417,6 @@ public override void WriteBytes( byte header, double value )
307417

308418
bufferRemaining = currentBufferLimit - currentBufferOffset;
309419
}
310-
311-
this._currentBufferIndex = currentBufferIndex;
312-
this._currentBuffer = currentBuffer;
313-
this._currentBufferOffset = currentBufferOffset;
314-
this._currentBufferLimit = currentBufferLimit;
315420
}
316421

317422
public override void WriteBytes( string value, bool allowStr8 )
@@ -475,4 +580,4 @@ private unsafe void WriteStringBody( string value )
475580
}
476581
}
477582
}
478-
}
583+
}

0 commit comments

Comments
 (0)