Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf9f0fd7

Browse files
author
dse
committed
Managed to python string marshaling cache added.
1 parentebf1fb0 commitf9f0fd7

File tree

2 files changed

+107
-21
lines changed

2 files changed

+107
-21
lines changed

‎CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
88
##[unreleased][]
99

1010
###Added
11+
- Improved performance. String marshaling between python and clr now cached.
12+
Cache reduces GC pressure and saves from extensive memory copying.
1113
- Added support for embedding python into dotnet core 2.0 (NetStandard 2.0)
1214
- Added new build system (pythonnet.15.sln) based on dotnetcore-sdk/xplat(crossplatform msbuild).
1315
Currently there two side-by-side build systems that produces the same output (net40) from the same sources.

‎src/runtime/CustomMarshaler.cs

Lines changed: 105 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public object MarshalNativeToManaged(IntPtr pNativeData)
1818

1919
publicabstractIntPtrMarshalManagedToNative(objectmanagedObj);
2020

21-
publicvoidCleanUpNativeData(IntPtrpNativeData)
21+
publicvirtualvoidCleanUpNativeData(IntPtrpNativeData)
2222
{
2323
Marshal.FreeHGlobal(pNativeData);
2424
}
@@ -44,7 +44,12 @@ internal class UcsMarshaler : MarshalerBase
4444
privatestaticreadonlyMarshalerBaseInstance=newUcsMarshaler();
4545
privatestaticreadonlyEncodingPyEncoding=Runtime.PyEncoding;
4646

47-
publicoverrideIntPtrMarshalManagedToNative(objectmanagedObj)
47+
privateconstintMaxStringLength=100;
48+
privateconstintMaxItemSize=4*(MaxStringLength+1);
49+
privatestaticreadonlyEncodedStringsFifoDictionaryEncodedStringsDictionary=
50+
newEncodedStringsFifoDictionary(10000,MaxItemSize);
51+
52+
publicoverrideunsafeIntPtrMarshalManagedToNative(objectmanagedObj)
4853
{
4954
vars=managedObjasstring;
5055

@@ -53,16 +58,36 @@ public override IntPtr MarshalManagedToNative(object managedObj)
5358
returnIntPtr.Zero;
5459
}
5560

56-
byte[]bStr=PyEncoding.GetBytes(s+"\0");
57-
IntPtrmem=Marshal.AllocHGlobal(bStr.Length);
58-
try
61+
IntPtrmem;
62+
intstringBytesCount;
63+
if(s.Length<=MaxStringLength)
5964
{
60-
Marshal.Copy(bStr,0,mem,bStr.Length);
65+
if(EncodedStringsDictionary.TryGetValue(s,outmem))
66+
{
67+
returnmem;
68+
}
69+
70+
stringBytesCount=PyEncoding.GetByteCount(s);
71+
mem=EncodedStringsDictionary.AddUnsafe(s);
6172
}
62-
catch(Exception)
73+
else
6374
{
64-
Marshal.FreeHGlobal(mem);
65-
throw;
75+
stringBytesCount=PyEncoding.GetByteCount(s);
76+
mem=Marshal.AllocHGlobal(stringBytesCount+4);
77+
}
78+
79+
fixed(char*str=s)
80+
{
81+
try
82+
{
83+
PyEncoding.GetBytes(str,s.Length,(byte*)mem,stringBytesCount);
84+
}
85+
catch
86+
{
87+
// Do nothing with this. Very strange problem.
88+
}
89+
90+
*(int*)(mem+stringBytesCount)=0;
6691
}
6792

6893
returnmem;
@@ -106,6 +131,14 @@ public static int GetUnicodeByteLength(IntPtr p)
106131
}
107132
}
108133

134+
publicoverridevoidCleanUpNativeData(IntPtrpNativeData)
135+
{
136+
if(!EncodedStringsDictionary.IsKnownPtr(pNativeData))
137+
{
138+
base.CleanUpNativeData(pNativeData);
139+
}
140+
}
141+
109142
/// <summary>
110143
/// Utility function for Marshaling Unicode on PY3 and AnsiStr on PY2.
111144
/// Use on functions whose Input signatures changed between PY2/PY3.
@@ -118,11 +151,29 @@ public static int GetUnicodeByteLength(IntPtr p)
118151
/// <remarks>
119152
/// You MUST deallocate the IntPtr of the Return when done with it.
120153
/// </remarks>
121-
publicstaticIntPtrPy3UnicodePy2StringtoPtr(strings)
154+
publicunsafestaticIntPtrPy3UnicodePy2StringtoPtr(strings)
122155
{
123-
returnRuntime.IsPython3
124-
?Instance.MarshalManagedToNative(s)
125-
:Marshal.StringToHGlobalAnsi(s);
156+
if(Runtime.IsPython3)
157+
{
158+
intstringBytesCount=PyEncoding.GetByteCount(s);
159+
IntPtrmem=Marshal.AllocHGlobal(stringBytesCount+4);
160+
fixed(char*str=s)
161+
{
162+
try
163+
{
164+
PyEncoding.GetBytes(str,s.Length,(byte*)mem,stringBytesCount);
165+
}
166+
catch
167+
{
168+
// Do nothing with this. Very strange problem.
169+
}
170+
171+
*(int*)(mem+stringBytesCount)=0;
172+
}
173+
returnmem;
174+
}
175+
176+
returnMarshal.StringToHGlobalAnsi(s);
126177
}
127178

128179
/// <summary>
@@ -208,7 +259,12 @@ internal class Utf8Marshaler : MarshalerBase
208259
privatestaticreadonlyMarshalerBaseInstance=newUtf8Marshaler();
209260
privatestaticreadonlyEncodingPyEncoding=Encoding.UTF8;
210261

211-
publicoverrideIntPtrMarshalManagedToNative(objectmanagedObj)
262+
privateconstintMaxStringLength=100;
263+
264+
privatestaticreadonlyEncodedStringsFifoDictionaryEncodedStringsDictionary=
265+
newEncodedStringsFifoDictionary(10000,4*(MaxStringLength+1));
266+
267+
publicoverrideunsafeIntPtrMarshalManagedToNative(objectmanagedObj)
212268
{
213269
vars=managedObjasstring;
214270

@@ -217,21 +273,49 @@ public override IntPtr MarshalManagedToNative(object managedObj)
217273
returnIntPtr.Zero;
218274
}
219275

220-
byte[]bStr=PyEncoding.GetBytes(s+"\0");
221-
IntPtrmem=Marshal.AllocHGlobal(bStr.Length);
222-
try
276+
IntPtrmem;
277+
intstringBytesCount;
278+
if(s.Length<=MaxStringLength)
223279
{
224-
Marshal.Copy(bStr,0,mem,bStr.Length);
280+
if(EncodedStringsDictionary.TryGetValue(s,outmem))
281+
{
282+
returnmem;
283+
}
284+
285+
stringBytesCount=PyEncoding.GetByteCount(s);
286+
mem=EncodedStringsDictionary.AddUnsafe(s);
225287
}
226-
catch(Exception)
288+
else
227289
{
228-
Marshal.FreeHGlobal(mem);
229-
throw;
290+
stringBytesCount=PyEncoding.GetByteCount(s);
291+
mem=Marshal.AllocHGlobal(stringBytesCount+1);
292+
}
293+
294+
fixed(char*str=s)
295+
{
296+
try
297+
{
298+
PyEncoding.GetBytes(str,s.Length,(byte*)mem,stringBytesCount);
299+
}
300+
catch
301+
{
302+
// Do nothing with this. Very strange problem.
303+
}
304+
305+
((byte*)mem)[stringBytesCount]=0;
230306
}
231307

232308
returnmem;
233309
}
234310

311+
publicoverridevoidCleanUpNativeData(IntPtrpNativeData)
312+
{
313+
if(!EncodedStringsDictionary.IsKnownPtr(pNativeData))
314+
{
315+
base.CleanUpNativeData(pNativeData);
316+
}
317+
}
318+
235319
publicstaticICustomMarshalerGetInstance(stringcookie)
236320
{
237321
returnInstance;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp