Skip to content

Commit 98cbbfd

Browse files
authored
MemoryCopy instead of Marshal.Copy + easier connection reuse (#9983)
* MemoryCopy instead of Marshal.Copy * Simplier connection reuse * Faster MemoryCopy for all data access --------- Co-authored-by: LLT21 <>
1 parent a4775c3 commit 98cbbfd

File tree

8 files changed

+52
-79
lines changed

8 files changed

+52
-79
lines changed

frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnection.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ private void GetConnection()
5454
if (_keyed)
5555
{
5656
(_number, _odbcConnection, _keyedOdbcCommands) =
57-
DbConnectionsKeyed.GetConnectionBase(_connectionString).GetAwaiter().GetResult();
57+
DbConnectionsKeyed.GetConnectionBase(_connectionString);
5858
}
5959
else
6060
{
61-
(_number, _odbcConnection, _odbcCommands) =
62-
DbConnections.GetConnectionBase(_connectionString).GetAwaiter().GetResult();
61+
(_number, _odbcConnection, _odbcCommands) =
62+
DbConnections.GetConnectionBase(_connectionString);
6363
}
6464
}
6565

frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnections.cs

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,57 +5,26 @@ namespace appMpower.Orm.Data
55
{
66
internal static class DbConnections
77
{
8-
private static bool _maxConnectionsCreated = false;
98
private static short _createdConnections = 0;
10-
private static short _maxConnections = 500;
119

1210
private static ConcurrentStack<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> _connectionsStack = new();
13-
private static ConcurrentQueue<TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)>> _waitingQueue = new();
1411

15-
internal static async Task<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> GetConnectionBase(string connectionString)
12+
internal static (int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands) GetConnectionBase(string connectionString)
1613
{
1714
(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands) dbConnectionBase;
1815

1916
if (!_connectionsStack.TryPop(out dbConnectionBase))
2017
{
21-
if (_maxConnectionsCreated)
22-
{
23-
dbConnectionBase = await GetDbConnectionBaseAsync();
24-
}
25-
else
26-
{
27-
_createdConnections++;
28-
dbConnectionBase = (Number: _maxConnections, OdbcConnection: new OdbcConnection(connectionString), OdbcCommands: new ConcurrentStack<OdbcCommand>());
29-
30-
if (_createdConnections == _maxConnections) _maxConnectionsCreated = true;
31-
32-
//Console.WriteLine("opened connection number: " + dbConnectionBase._number);
33-
}
18+
_createdConnections++;
19+
dbConnectionBase = (Number: _createdConnections, OdbcConnection: new OdbcConnection(connectionString), OdbcCommands: new ConcurrentStack<OdbcCommand>());
3420
}
3521

3622
return dbConnectionBase;
3723
}
3824

3925
internal static void Release((int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands) dbConnectionBase)
4026
{
41-
TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> taskCompletionSource;
42-
43-
if (_waitingQueue.TryDequeue(out taskCompletionSource))
44-
{
45-
taskCompletionSource.SetResult(dbConnectionBase);
46-
}
47-
else
48-
{
49-
_connectionsStack.Push(dbConnectionBase);
50-
}
51-
}
52-
53-
private static Task<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)> GetDbConnectionBaseAsync()
54-
{
55-
var taskCompletionSource = new TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, ConcurrentStack<OdbcCommand> OdbcCommands)>(TaskCreationOptions.RunContinuationsAsynchronously);
56-
57-
_waitingQueue.Enqueue(taskCompletionSource);
58-
return taskCompletionSource.Task;
27+
_connectionsStack.Push(dbConnectionBase);
5928
}
6029
}
6130
}

frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnectionsKeyed.cs

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,57 +5,26 @@ namespace appMpower.Orm.Data
55
{
66
internal static class DbConnectionsKeyed
77
{
8-
private static bool _maxConnectionsCreated = false;
98
private static short _createdConnections = 0;
10-
private static short _maxConnections = 500;
119

1210
private static ConcurrentStack<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)> _connectionsStack = new();
13-
private static ConcurrentQueue<TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)>> _waitingQueue = new();
1411

15-
internal static async Task<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand> KeyedOdbcCommands)> GetConnectionBase(string connectionString)
12+
internal static (int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand> KeyedOdbcCommands) GetConnectionBase(string connectionString)
1613
{
1714
(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand> KeyedOdbcCommands) dbConnectionBase;
1815

1916
if (!_connectionsStack.TryPop(out dbConnectionBase))
2017
{
21-
if (_maxConnectionsCreated)
22-
{
23-
dbConnectionBase = await GetDbConnectionBaseAsync();
24-
}
25-
else
26-
{
27-
_createdConnections++;
28-
dbConnectionBase = (Number: _maxConnections, OdbcConnection: new OdbcConnection(connectionString), KeyedOdbcCommands: new Dictionary<string, OdbcCommand>());
29-
30-
if (_createdConnections == _maxConnections) _maxConnectionsCreated = true;
31-
32-
//Console.WriteLine("opened connection number: " + dbConnectionBase._number);
33-
}
18+
_createdConnections++;
19+
dbConnectionBase = (Number: _createdConnections, OdbcConnection: new OdbcConnection(connectionString), KeyedOdbcCommands: new Dictionary<string, OdbcCommand>());
3420
}
3521

3622
return dbConnectionBase;
3723
}
3824

3925
internal static void Release((int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand> KeyedOdbcCommands) dbConnectionBase)
4026
{
41-
TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)> taskCompletionSource;
42-
43-
if (_waitingQueue.TryDequeue(out taskCompletionSource))
44-
{
45-
taskCompletionSource.SetResult(dbConnectionBase);
46-
}
47-
else
48-
{
49-
_connectionsStack.Push(dbConnectionBase);
50-
}
51-
}
52-
53-
private static Task<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)> GetDbConnectionBaseAsync()
54-
{
55-
var taskCompletionSource = new TaskCompletionSource<(int Number, OdbcConnection OdbcConnection, Dictionary<string, OdbcCommand>)>(TaskCreationOptions.RunContinuationsAsynchronously);
56-
57-
_waitingQueue.Enqueue(taskCompletionSource);
58-
return taskCompletionSource.Task;
27+
_connectionsStack.Push(dbConnectionBase);
5928
}
6029
}
6130
}

frameworks/CSharp/appmpower/src/appMpower/Middleware/CachingMiddelware.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ public unsafe Task Invoke(HttpContext httpContext)
4646
{
4747
bytePointer = NativeMethods.DbById(i, out payloadLength, out handlePointer);
4848
json = new byte[payloadLength];
49-
Marshal.Copy(bytePointer, json, 0, payloadLength);
49+
//Marshal.Copy(bytePointer, json, 0, payloadLength);
50+
51+
fixed (byte* dest = json)
52+
{
53+
Buffer.MemoryCopy((void*)bytePointer, dest, payloadLength, payloadLength);
54+
}
55+
5056
NativeMethods.FreeHandlePointer(handlePointer);
5157
_cache.Add(i, json);
5258
}
@@ -72,7 +78,13 @@ public unsafe Task Invoke(HttpContext httpContext)
7278
{
7379
bytePointer = NativeMethods.DbById(keys[i], out payloadLength, out handlePointer);
7480
json = new byte[payloadLength];
75-
Marshal.Copy(bytePointer, json, 0, payloadLength);
81+
//Marshal.Copy(bytePointer, json, 0, payloadLength);
82+
83+
fixed (byte* dest = json)
84+
{
85+
Buffer.MemoryCopy((void*)bytePointer, dest, payloadLength, payloadLength);
86+
}
87+
7688
NativeMethods.FreeHandlePointer(handlePointer);
7789
_cache.Add(keys[i], json);
7890
}

frameworks/CSharp/appmpower/src/appMpower/Middleware/FortunesMiddleware.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,12 @@ public unsafe Task Invoke(HttpContext httpContext)
7070
*/
7171

7272
byte[] byteArray = new byte[payloadLength];
73-
Marshal.Copy(bytePointer, byteArray, 0, payloadLength);
73+
//Marshal.Copy(bytePointer, json, 0, payloadLength);
74+
75+
fixed (byte* dest = byteArray)
76+
{
77+
Buffer.MemoryCopy((void*)bytePointer, dest, payloadLength, payloadLength);
78+
}
7479

7580
List<Fortune> fortunes = new List<Fortune>();
7681

frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleQueriesMiddleware.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@ public unsafe Task Invoke(HttpContext httpContext)
4040

4141
IntPtr bytePointer = NativeMethods.Query(queries, out payloadLength, out handlePointer);
4242
byte[] json = new byte[payloadLength];
43-
Marshal.Copy(bytePointer, json, 0, payloadLength);
43+
//Marshal.Copy(bytePointer, json, 0, payloadLength);
44+
45+
fixed (byte* dest = json)
46+
{
47+
Buffer.MemoryCopy((void*)bytePointer, dest, payloadLength, payloadLength);
48+
}
49+
4450
NativeMethods.FreeHandlePointer(handlePointer);
4551

4652
response.Headers.Add(

frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleUpdatesMiddleware.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@ public unsafe Task Invoke(HttpContext httpContext)
4040

4141
IntPtr bytePointer = NativeMethods.Updates(count, out payloadLength, out handlePointer);
4242
byte[] json = new byte[payloadLength];
43-
Marshal.Copy(bytePointer, json, 0, payloadLength);
43+
//Marshal.Copy(bytePointer, json, 0, payloadLength);
44+
45+
fixed (byte* dest = json)
46+
{
47+
Buffer.MemoryCopy((void*)bytePointer, dest, payloadLength, payloadLength);
48+
}
49+
4450
NativeMethods.FreeHandlePointer(handlePointer);
4551

4652
response.Headers.Add(

frameworks/CSharp/appmpower/src/appMpower/Middleware/SingleQueryMiddleware.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,13 @@ public unsafe Task Invoke(HttpContext httpContext)
3535

3636
IntPtr bytePointer = NativeMethods.Db(out payloadLength, out handlePointer);
3737
byte[] json = new byte[payloadLength];
38-
Marshal.Copy(bytePointer, json, 0, payloadLength);
38+
//Marshal.Copy(bytePointer, json, 0, payloadLength);
39+
40+
fixed (byte* dest = json)
41+
{
42+
Buffer.MemoryCopy((void*)bytePointer, dest, payloadLength, payloadLength);
43+
}
44+
3945
NativeMethods.FreeHandlePointer(handlePointer);
4046

4147
response.Headers.Add(

0 commit comments

Comments
 (0)