Skip to content

Commit 960895e

Browse files
committed
Use Span<byte> in BinaryConverter
1 parent ba9c973 commit 960895e

File tree

5 files changed

+123
-182
lines changed

5 files changed

+123
-182
lines changed

Enyim.Caching/Memcached/MemcachedNode.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
using Enyim.Caching.Configuration;
2-
using Enyim.Caching.Memcached.Protocol.Binary;
3-
using Enyim.Caching.Memcached.Results;
4-
using Enyim.Caching.Memcached.Results.Extensions;
5-
using Enyim.Collections;
6-
using Microsoft.Extensions.Logging;
71
using System;
82
using System.Collections.Generic;
93
using System.Diagnostics;
@@ -13,6 +7,12 @@
137
using System.Security;
148
using System.Threading;
159
using System.Threading.Tasks;
10+
using Enyim.Caching.Configuration;
11+
using Enyim.Caching.Memcached.Protocol.Binary;
12+
using Enyim.Caching.Memcached.Results;
13+
using Enyim.Caching.Memcached.Results.Extensions;
14+
using Enyim.Collections;
15+
using Microsoft.Extensions.Logging;
1616

1717
namespace Enyim.Caching.Memcached
1818
{

Enyim.Caching/Memcached/Protocol/Binary/BinaryConverter.cs

Lines changed: 28 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -5,110 +5,58 @@ namespace Enyim.Caching.Memcached.Protocol.Binary
55
{
66
public static class BinaryConverter
77
{
8-
public static unsafe ushort DecodeUInt16(byte[] buffer, int offset)
8+
public static ushort DecodeUInt16(Span<byte> buffer, int offset)
99
{
1010
return (ushort)((buffer[offset] << 8) + buffer[offset + 1]);
1111
}
1212

13-
public static unsafe ushort DecodeUInt16(byte* buffer, int offset)
13+
public static int DecodeInt32(Span<byte> buffer, int offset)
1414
{
15-
return (ushort)((buffer[offset] << 8) + buffer[offset + 1]);
16-
}
17-
18-
public static unsafe int DecodeInt32(ArraySegment<byte> segment, int offset)
19-
{
20-
fixed (byte* buffer = segment.Array)
21-
{
22-
byte* ptr = buffer + segment.Offset + offset;
23-
24-
return DecodeInt32(buffer, 0);
25-
}
26-
}
27-
28-
public static unsafe int DecodeInt32(byte* buffer, int offset)
29-
{
30-
buffer += offset;
31-
32-
return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
33-
}
34-
35-
public static unsafe int DecodeInt32(byte[] buffer, int offset)
36-
{
37-
return (buffer[offset] << 24) | (buffer[offset + 1] << 16) | (buffer[offset + 2] << 8) | buffer[offset + 3];
38-
}
15+
var slice = buffer.Slice(offset);
3916

40-
public static unsafe ulong DecodeUInt64(byte[] buffer, int offset)
41-
{
42-
fixed (byte* ptr = buffer)
43-
{
44-
return DecodeUInt64(ptr, offset);
45-
}
17+
return (slice[0] << 24) | (slice[1] << 16) | (slice[2] << 8) | slice[3];
4618
}
4719

48-
public static unsafe ulong DecodeUInt64(byte* buffer, int offset)
20+
public static unsafe ulong DecodeUInt64(Span<byte> buffer, int offset)
4921
{
50-
buffer += offset;
22+
var slice = buffer.Slice(offset);
5123

52-
var part1 = (uint)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]);
53-
var part2 = (uint)((buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]);
24+
var part1 = (uint)((slice[0] << 24) | (slice[1] << 16) | (slice[2] << 8) | slice[3]);
25+
var part2 = (uint)((slice[4] << 24) | (slice[5] << 16) | (slice[6] << 8) | slice[7]);
5426

5527
return ((ulong)part1 << 32) | part2;
5628
}
5729

58-
public static unsafe void EncodeUInt16(uint value, byte[] buffer, int offset)
59-
{
60-
fixed (byte* bufferPtr = buffer)
61-
{
62-
EncodeUInt16(value, bufferPtr, offset);
63-
}
64-
}
65-
66-
public static unsafe void EncodeUInt16(uint value, byte* buffer, int offset)
30+
public static unsafe void EncodeUInt16(uint value, Span<byte> buffer, int offset)
6731
{
68-
byte* ptr = buffer + offset;
32+
var slice = buffer.Slice(offset);
6933

70-
ptr[0] = (byte)(value >> 8);
71-
ptr[1] = (byte)(value & 255);
34+
slice[0] = (byte)(value >> 8);
35+
slice[1] = (byte)(value & 255);
7236
}
7337

74-
public static unsafe void EncodeUInt32(uint value, byte[] buffer, int offset)
38+
public static unsafe void EncodeUInt32(uint value, Span<byte> buffer, int offset)
7539
{
76-
fixed (byte* bufferPtr = buffer)
77-
{
78-
EncodeUInt32(value, bufferPtr, offset);
79-
}
80-
}
81-
82-
public static unsafe void EncodeUInt32(uint value, byte* buffer, int offset)
83-
{
84-
byte* ptr = buffer + offset;
40+
var slice = buffer.Slice(offset);
8541

86-
ptr[0] = (byte)(value >> 24);
87-
ptr[1] = (byte)(value >> 16);
88-
ptr[2] = (byte)(value >> 8);
89-
ptr[3] = (byte)(value & 255);
42+
slice[0] = (byte)(value >> 24);
43+
slice[1] = (byte)(value >> 16);
44+
slice[2] = (byte)(value >> 8);
45+
slice[3] = (byte)(value & 255);
9046
}
9147

92-
public static unsafe void EncodeUInt64(ulong value, byte[] buffer, int offset)
48+
public static unsafe void EncodeUInt64(ulong value, Span<byte> buffer, int offset)
9349
{
94-
fixed (byte* bufferPtr = buffer)
95-
{
96-
EncodeUInt64(value, bufferPtr, offset);
97-
}
98-
}
50+
var slice = buffer.Slice(offset);
9951

100-
public static unsafe void EncodeUInt64(ulong value, byte* buffer, int offset)
101-
{
102-
byte* ptr = buffer + offset;
103-
104-
ptr[0] = (byte)(value >> 56);
105-
ptr[1] = (byte)(value >> 48);
106-
ptr[2] = (byte)(value >> 40);
107-
ptr[3] = (byte)(value >> 32);
108-
ptr[4] = (byte)(value >> 24);
109-
ptr[5] = (byte)(value >> 16);
110-
ptr[6] = (byte)(value >> 8);
111-
ptr[7] = (byte)(value & 255);
52+
slice[0] = (byte)(value >> 56);
53+
slice[1] = (byte)(value >> 48);
54+
slice[2] = (byte)(value >> 40);
55+
slice[3] = (byte)(value >> 32);
56+
slice[4] = (byte)(value >> 24);
57+
slice[5] = (byte)(value >> 16);
58+
slice[6] = (byte)(value >> 8);
59+
slice[7] = (byte)(value & 255);
11260
}
11361

11462
public static byte[] EncodeKey(string key)

Enyim.Caching/Memcached/Protocol/Binary/BinaryResponse.cs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System;
2-
using System.Text;
32
using System.Diagnostics;
3+
using System.Text;
44
using System.Threading.Tasks;
55

66
namespace Enyim.Caching.Memcached.Protocol.Binary
@@ -64,7 +64,7 @@ public unsafe bool Read(PooledSocket socket)
6464
if (dataLength > 0)
6565
{
6666
var data = new byte[dataLength];
67-
socket.Read(data, 0, dataLength);
67+
socket.Read(data, 0, dataLength);
6868

6969
this.Extra = new ArraySegment<byte>(data, 0, extraLength);
7070
this.Data = new ArraySegment<byte>(data, extraLength, data.Length - extraLength);
@@ -207,24 +207,22 @@ private void DoDecodeBody(AsyncIOArgs asyncEvent)
207207
if (this.shouldCallNext) this.next(true);
208208
}
209209

210-
private unsafe void DeserializeHeader(byte[] header, out int dataLength, out int extraLength)
210+
211+
private void DeserializeHeader(Span<byte> header, out int dataLength, out int extraLength)
211212
{
212-
fixed (byte* buffer = header)
213-
{
214-
if (buffer[0] != MAGIC_VALUE)
215-
throw new InvalidOperationException("Expected magic value " + MAGIC_VALUE + ", received: " + buffer[0]);
213+
if (header[0] != MAGIC_VALUE)
214+
throw new InvalidOperationException("Expected magic value " + MAGIC_VALUE + ", received: " + header[0]);
216215

217-
this.DataType = buffer[HEADER_DATATYPE];
218-
this.Opcode = buffer[HEADER_OPCODE];
219-
this.StatusCode = BinaryConverter.DecodeUInt16(buffer, HEADER_STATUS);
216+
this.DataType = header[HEADER_DATATYPE];
217+
this.Opcode = header[HEADER_OPCODE];
218+
this.StatusCode = BinaryConverter.DecodeUInt16(header, HEADER_STATUS);
220219

221-
this.KeyLength = BinaryConverter.DecodeUInt16(buffer, HEADER_KEY);
222-
this.CorrelationId = BinaryConverter.DecodeInt32(buffer, HEADER_OPAQUE);
223-
this.CAS = BinaryConverter.DecodeUInt64(buffer, HEADER_CAS);
220+
this.KeyLength = BinaryConverter.DecodeUInt16(header, HEADER_KEY);
221+
this.CorrelationId = BinaryConverter.DecodeInt32(header, HEADER_OPAQUE);
222+
this.CAS = BinaryConverter.DecodeUInt64(header, HEADER_CAS);
224223

225-
dataLength = BinaryConverter.DecodeInt32(buffer, HEADER_BODY);
226-
extraLength = buffer[HEADER_EXTRA];
227-
}
224+
dataLength = BinaryConverter.DecodeInt32(header, HEADER_BODY);
225+
extraLength = header[HEADER_EXTRA];
228226
}
229227

230228
private void LogExecutionTime(string title, DateTime startTime, int thresholdMs)

Enyim.Caching/Memcached/Protocol/Binary/GetOperation.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Text;
34
using Enyim.Caching.Memcached.Results;
@@ -37,7 +38,7 @@ protected override IOperationResult ProcessResponse(BinaryResponse response)
3738

3839
if (status == 0)
3940
{
40-
int flags = BinaryConverter.DecodeInt32(response.Extra, 0);
41+
int flags = BinaryConverter.DecodeInt32(response.Extra.AsSpan(), 0);
4142
this.result = new CacheItem((ushort)flags, response.Data);
4243
this.Cas = response.CAS;
4344

Enyim.Caching/Memcached/Protocol/Binary/MutatorOperation.cs

Lines changed: 73 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,82 @@
11
using System;
2+
using Enyim.Caching.Memcached.Results;
23
using Enyim.Caching.Memcached.Results.Extensions;
34
using Enyim.Caching.Memcached.Results.Helpers;
4-
using Enyim.Caching.Memcached.Results;
55

66
namespace Enyim.Caching.Memcached.Protocol.Binary
77
{
8-
public class MutatorOperation : BinarySingleItemOperation, IMutatorOperation
9-
{
10-
private ulong defaultValue;
11-
private ulong delta;
12-
private uint expires;
13-
private MutationMode mode;
14-
private ulong result;
15-
16-
public MutatorOperation(MutationMode mode, string key, ulong defaultValue, ulong delta, uint expires)
17-
: base(key)
18-
{
19-
if (delta < 0) throw new ArgumentOutOfRangeException("delta", "delta must be >= 0");
20-
21-
this.defaultValue = defaultValue;
22-
this.delta = delta;
23-
this.expires = expires;
24-
this.mode = mode;
25-
}
26-
27-
protected unsafe void UpdateExtra(BinaryRequest request)
28-
{
29-
byte[] extra = new byte[20];
30-
31-
fixed (byte* buffer = extra)
32-
{
33-
BinaryConverter.EncodeUInt64(this.delta, buffer, 0);
34-
35-
BinaryConverter.EncodeUInt64(this.defaultValue, buffer, 8);
36-
BinaryConverter.EncodeUInt32(this.expires, buffer, 16);
37-
}
38-
39-
request.Extra = new ArraySegment<byte>(extra);
40-
}
41-
42-
protected override BinaryRequest Build()
43-
{
44-
var request = new BinaryRequest((OpCode)this.mode)
45-
{
46-
Key = this.Key,
47-
Cas = this.Cas
48-
};
49-
50-
this.UpdateExtra(request);
51-
52-
return request;
53-
}
54-
55-
protected override IOperationResult ProcessResponse(BinaryResponse response)
56-
{
57-
var result = new BinaryOperationResult();
58-
var status = response.StatusCode;
59-
this.StatusCode = status;
60-
61-
if (status == 0)
62-
{
63-
var data = response.Data;
64-
if (data.Count != 8)
65-
return result.Fail("Result must be 8 bytes long, received: " + data.Count, new InvalidOperationException());
66-
67-
this.result = BinaryConverter.DecodeUInt64(data.Array, data.Offset);
68-
69-
return result.Pass();
70-
}
71-
72-
var message = ResultHelper.ProcessResponseData(response.Data);
73-
return result.Fail(message);
74-
}
75-
76-
MutationMode IMutatorOperation.Mode
77-
{
78-
get { return this.mode; }
79-
}
80-
81-
ulong IMutatorOperation.Result
82-
{
83-
get { return this.result; }
84-
}
85-
}
8+
public class MutatorOperation : BinarySingleItemOperation, IMutatorOperation
9+
{
10+
private readonly ulong defaultValue;
11+
private readonly ulong delta;
12+
private readonly uint expires;
13+
private readonly MutationMode mode;
14+
private ulong result;
15+
16+
public MutatorOperation(MutationMode mode, string key, ulong defaultValue, ulong delta, uint expires)
17+
: base(key)
18+
{
19+
if (delta < 0) throw new ArgumentOutOfRangeException("delta", "delta must be >= 0");
20+
21+
this.defaultValue = defaultValue;
22+
this.delta = delta;
23+
this.expires = expires;
24+
this.mode = mode;
25+
}
26+
27+
protected void UpdateExtra(BinaryRequest request)
28+
{
29+
Span<byte> buffer = stackalloc byte[20];
30+
BinaryConverter.EncodeUInt64(this.delta, buffer, 0);
31+
BinaryConverter.EncodeUInt64(this.defaultValue, buffer, 8);
32+
BinaryConverter.EncodeUInt32(this.expires, buffer, 16);
33+
request.Extra = new ArraySegment<byte>(buffer.ToArray());
34+
}
35+
36+
protected override BinaryRequest Build()
37+
{
38+
var request = new BinaryRequest((OpCode)this.mode)
39+
{
40+
Key = this.Key,
41+
Cas = this.Cas
42+
};
43+
44+
this.UpdateExtra(request);
45+
46+
return request;
47+
}
48+
49+
protected override IOperationResult ProcessResponse(BinaryResponse response)
50+
{
51+
var result = new BinaryOperationResult();
52+
var status = response.StatusCode;
53+
this.StatusCode = status;
54+
55+
if (status == 0)
56+
{
57+
var data = response.Data;
58+
if (data.Count != 8)
59+
return result.Fail("Result must be 8 bytes long, received: " + data.Count, new InvalidOperationException());
60+
61+
this.result = BinaryConverter.DecodeUInt64(data.Array, data.Offset);
62+
63+
return result.Pass();
64+
}
65+
66+
var message = ResultHelper.ProcessResponseData(response.Data);
67+
return result.Fail(message);
68+
}
69+
70+
MutationMode IMutatorOperation.Mode
71+
{
72+
get { return this.mode; }
73+
}
74+
75+
ulong IMutatorOperation.Result
76+
{
77+
get { return this.result; }
78+
}
79+
}
8680
}
8781

8882
#region [ License information ]

0 commit comments

Comments
 (0)