素晴らしい図書館マイク、この巨大な仕事に感謝します。
問題は、InputReportにデータを入力する場合です。
InputReport = device.ReadReport();
ここで、InputReportは次のとおりです。
HidLibrary.HidReport InputReport = new HidLibrary.HidReport(device.Capabilities.InputReportByteLength);
特にデバイスから非同期モードでレポートを読み取る場合(たとえば、1秒間に100回)、これは非常に大きなリークメモリです。 数分で数百メガバイトかかることがあります。
私はC#プログラミングの初心者であり、上記で説明した問題の解決策が見つかりませんでした;(
あいさつ!
Kaczart、
残念ながら、そのコードはかなり古く、私はそれを与える時間がありませんでした
任意のTLC。 この時点で、私はそれを参照としてそこに持っています。 あなたの最高の
賭けはフォーク/改善することです。
NS
2011年8月14日日曜日午前10時37分、kaczart <
[email protected]>書き込み:
素晴らしい図書館マイク、この巨大な仕事に感謝します。
問題は、InputReportにデータを入力する場合です。
InputReport = device.ReadReport();
ここで、InputReportは次のとおりです。
HidLibrary.HidReport InputReport = new
HidLibrary.HidReport(ukp.Capabilities.InputReportByteLength);特に非同期でレポートを読む場合、これは非常に大きなリークメモリです。
デバイスからのモード(たとえば、1秒間に100回)。 数分でそれができます
数百メガバイトかかります。私はC#プログラミングの初心者ですが、問題の解決策が見つかりませんでした
上記の説明;(あいさつ!
このメールに直接返信するか、GitHubで表示してください。
https://github.com/mikeobrien/HidLibrary/issues/11
Kaczart、
解決策を見つけましたか? 私はちょうど同じことに気づきました。
素晴らしい図書館マイク、どうもありがとう! 私はエンディシアのUSBスケールで作業していますが、これはとても楽しいです。
jrockfl、
残念ながら、この問題を解決するのに十分な時間とスキルがありませんでした:(
あいさつ
問題は、HidReportとDevicedataが解放されないため、ガベージコレクションを待機することです。
処理後にリリースするのは簡単な修正です...
最後に、この問題を修正する必要があり、見つけたものを共有します
1)まず、ライブラリ内のすべての読み取り/書き込みメソッドは、デバイスが接続されているかどうかを確認します。これは、IsConnectedメソッドがEnumerateHidDevices()を呼び出すたびに呼び出されるため、パフォーマンスが大幅に低下します。 実際には、デバイスから大きなデータパッケージを送信すると、PCホストはHIDデバイスよりも遅くなり、リングバッファーが制限されているために一部のパケットが失われます(デフォルトでは32レポートを512に拡張できますが、最終的な解決策ではありません)。
ps。 リングバッファを32から最大512のレポートに拡張できます。
NativeMethods .HidD_SetNumInputBuffers((int)device.ReadHandle、512); // XP以降で動作します。
2)次に、EnumerateHidDevices()には、「yieldreturndevicePath」による大量のメモリリークがあります。 69行目およびNativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet); 呼び出されることはありません。
私の解決策:
1)読み取り/書き込みごとにIsConnectedを呼び出さないでください。 HidDeviceに追加のisConnected変数を作成します。
public bool isConnected;
接続が成功した後(たとえば、Connect()関数で)変数をtrueに設定します。
device.isConnected = true;
すべてのDeviceEventMonitorInserted()およびDeviceEventMonitorRemoved()イベントで更新します。例:
if(Inserted!= null)Inserted();
と置換する:
if(挿入!= null)
{{
isConnected = true;
Inserted();
}
と:
if(Removed!= null)Removed();
と置換する:
if(削除されました!= null)
{{
isConnected = false;
NS();
}
読み取り/書き込み呼び出し関数ごとにこの変数をチェックするよりも:
if(IsConnected)の代わりにif(isConnected)
デバイスが接続されているかどうかを確認する必要があるたびに、パブリック変数isConnectedの状態を確認してください。 それは私のために働きます-読み取りスレッドの10-20%の代わりに0-1%のプロセッサ使用量。
2)HidDevice.csの69行目で削除:
//利回りreturndevicePath;
NativeMethods .SetupDiDestroyDeviceInfoList(deviceInfoSet);が可能になります。 ふさわしく呼ばれる。
次に、NativeMethods .SetupDiDestroyDeviceInfoList(deviceInfoSet)の後に次を追加します。
foreach(デバイス内の文字列devicePath)
リターンdevicePathを生成します。
巨大なメモリリークを修正します(私の場合、1MBの受信データごとに約256MB)
それが盛り上がることを願っています。
素晴らしい、あなたのヒントをありがとう、kaczart !!!
kaczart(および私)が気付いたパフォーマンスの問題に対する私の推奨される回避策は次のとおりです。
https://github.com/macaba/HidLibrary/commit/8f1864e1351ccca4772d5bbc18a0f94d7ba07fe7
使用法は次の線に沿っています:
device.ConnectionCheckOverride = device.IsConnected;
methodRequiringFasterUSBReadWrite();
device.ConnectionCheckOverride = false;
これにより、バルクUSB転送テストケースの実行時間が159秒から47秒に短縮されました。
IsConnectedプロパティがHidDeviceEventMonitorで使用されているという理由だけで、kaczartのソリューションに熱心ではなかったため、現在接続されているUSBデバイスを列挙する元の機能を保持する必要がありました。 簡単に言えば; InsertedイベントとRemovedイベントがkaczartのコードで呼び出されることはないと思います(簡単に見てみると)。
読み取りと書き込みのたびにデバイス接続をチェックすることは、高周波アプリケーションの主要なパフォーマンスのボトルネックです。 私の特定のケースでは、デバイスの接続を再確認するよりも、デバイスが接続されていると想定する方が30倍高速でした。 往復は約70msから2msに減少しました。
そこで、プーリングを迅速に使用するために独自のIOを処理するための拡張メソッドをいくつか作成しました。
[DllImport("hid.dll", SetLastError = true)]
static internal extern bool HidD_SetOutputReport(IntPtr hidDeviceObject, byte[] lpReportBuffer, int reportBufferLength);
[DllImport("kernel32.dll", SetLastError = true)]
static internal extern bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);
public static bool FastWrite(this HidLibrary.HidDevice device, byte[] outputBuffer)
{
try
{
if (NativeMethods.HidD_SetOutputReport(device.Handle, outputBuffer, outputBuffer.Length))
return true;
else
return false;
}
catch
{
return false;
}
}
public static ReadStatus FastRead(this HidLibrary.HidDevice device, byte[] inputBuffer)
{
try
{
uint bytesRead;
if (NativeMethods.ReadFile(device.Handle, inputBuffer, (uint)inputBuffer.Length, out bytesRead, IntPtr.Zero))
{
return ReadStatus.Success;
}
else
{
return ReadStatus.NoDataRead;
}
}
catch (Exception)
{
return ReadStatus.ReadError;
}
}
最も参考になるコメント
kaczart(および私)が気付いたパフォーマンスの問題に対する私の推奨される回避策は次のとおりです。
https://github.com/macaba/HidLibrary/commit/8f1864e1351ccca4772d5bbc18a0f94d7ba07fe7
使用法は次の線に沿っています:
これにより、バルクUSB転送テストケースの実行時間が159秒から47秒に短縮されました。
IsConnectedプロパティがHidDeviceEventMonitorで使用されているという理由だけで、kaczartのソリューションに熱心ではなかったため、現在接続されているUSBデバイスを列挙する元の機能を保持する必要がありました。 簡単に言えば; InsertedイベントとRemovedイベントがkaczartのコードで呼び出されることはないと思います(簡単に見てみると)。