Hidlibrary: ReadReport() kebocoran memori

Dibuat pada 14 Agu 2011  ·  9Komentar  ·  Sumber: mikeobrien/HidLibrary

Perpustakaan hebat Mike, terima kasih banyak untuk pekerjaan besar ini.

Masalahnya adalah ketika saya ingin mengisi InputReport dengan data:

InputReport = perangkat.ReadReport();

di mana InputReport adalah:

HidLibrary.HidReport InputReport = HidLibrary.HidReport baru(device.Capabilities.InputReportByteLength);

Ini adalah kebocoran memori yang sangat besar, khususnya ketika saya membaca laporan dalam mode asinkron dari perangkat (misalnya 100 kali per detik). Dalam beberapa menit dibutuhkan ratusan megabyte.

Saya pemula dalam pemrograman c # dan tidak menemukan solusi untuk masalah yang dijelaskan di atas;(

Salam pembuka!

Komentar yang paling membantu

Inilah solusi yang saya sarankan untuk masalah kinerja yang diperhatikan oleh kaczart (dan saya):
https://github.com/macaba/HidLibrary/commit/8f1864e1351ccca4772d5bbc18a0f94d7ba07fe7

Penggunaannya sejalan dengan:

device.ConnectionCheckOverride = device.IsConnected;
methodRequiringFasterUSBReadWrite();
device.ConnectionCheckOverride = false;

Ini mengurangi waktu eksekusi kasus uji transfer USB massal saya dari 159 detik menjadi 47 detik.

Saya tidak tertarik pada solusi kaczart hanya karena properti IsConnected digunakan di HidDeviceEventMonitor, jadi saya perlu mempertahankan fungsionalitas asli dari pencacahan perangkat USB yang saat ini terhubung. Sederhananya; Saya tidak berpikir acara yang Disisipkan dan Dihapus tidak akan pernah dipanggil dalam kode kaczart (dari tampilan singkatnya).

Semua 9 komentar

Kaczart,

Sayangnya kode itu sudah cukup lama dan saya belum punya waktu untuk memberikannya
TLC apa pun. Pada titik ini saya hanya memilikinya di luar sana sebagai referensi. terbaikmu
taruhan adalah untuk garpu/meningkatkan.

M

Pada Minggu, 14 Agustus 2011 pukul 10:37, kaczart <
[email protected]>menulis:

Perpustakaan hebat Mike, terima kasih banyak untuk pekerjaan besar ini.

Masalahnya adalah ketika saya ingin mengisi InputReport dengan data:

InputReport = perangkat.ReadReport();

di mana InputReport adalah:

HidLibrary.HidReport InputReport = baru
HidLibrary.HidReport(ukp.Capabilities.InputReportByteLength);

Ini adalah memori kebocoran yang sangat besar, khususnya ketika saya membaca laporan dalam async
mode dari perangkat (misalnya 100 kali per detik). Dalam beberapa menit bisa
membutuhkan ratusan megabyte.

Saya pemula dalam pemrograman c # dan tidak menemukan solusi untuk masalah
dijelaskan di atas ;(

Salam pembuka!

Balas email ini secara langsung atau lihat di GitHub:
https://github.com/mikeobrien/HidLibrary/issues/11

Kaczart,

Apakah Anda menemukan solusi? Saya baru saja memperhatikan hal yang sama.
Perpustakaan hebat Mike, terima kasih banyak! Saya bekerja dengan skala usb Endicia dan ini cukup menyenangkan.

jrockfl,

sayangnya saya tidak punya waktu dan keterampilan yang cukup untuk memperbaiki masalah ini :(

Salam pembuka

Masalahnya adalah HidReport dan Devicedata tidak dibebaskan, jadi menunggu pengumpulan sampah.
Ini adalah perbaikan yang mudah meskipun untuk melepaskannya setelah diproses ...

Akhirnya saya harus memperbaiki masalah ini dan saya membagikan apa yang saya temukan

1) Pertama-tama, setiap metode Baca/Tulis di perpustakaan memeriksa apakah perangkat terhubung apa yang menghabiskan banyak kinerja karena metode IsConnected memanggil setiap kali EnumerateHidDevices(). Dalam praktiknya, ketika saya mengirim paket data besar dari perangkat, Host PC lebih lambat dari perangkat HID dan beberapa paket hilang karena buffer cincin terbatas (32laporan secara default, dapat diperpanjang hingga 512 tetapi itu bukan solusi akhir).
hal. Anda dapat memperpanjang penyangga dering Anda dari 32 hingga maksimal 512 laporan dengan menelepon:
NativeMethods .HidD_SetNumInputBuffers((int )device.ReadHandle, 512); // Ini akan bekerja untuk XP dan yang lebih baru.
2) Kedua, di EnumerateHidDevices() adalah kebocoran memori BESAR karena "yield return devicePath;" pada baris 69 dan NativeMethods.SetupDiDestroyDeviceInfoList(deviceInfoSet); tidak akan pernah dipanggil.

Solusi saya:
1) Jangan panggil IsConnected setiap Baca/Tulis. Buat variabel isConnected tambahan di HidDevice:
boo publik Terhubung;
Setel variabel ke true setelah koneksi berhasil (mis. dalam fungsi Connect() Anda):
device.isConnected = benar;
Perbarui di setiap acara DeviceEventMonitorInserted() dan DeviceEventMonitorRemoved(), misalnya:
if (Disisipkan != null ) Disisipkan();
ubah dengan:
jika (Dimasukkan != null )
{
isConnected = benar;
dimasukkan();
}
dan:
if (Dihapus != null ) Dihapus();
ubah dengan:
jika (Dihapus != null )
{
isConnected = salah ;
DIHAPUS();
}
Daripada memeriksa variabel ini setiap fungsi panggilan Baca/Tulis:
if (isConnected) alih-alih if (IsConnected)
Setiap kali Anda perlu memeriksa apakah perangkat terhubung, periksa status variabel publik adalah Terhubung. Ini berfungsi untuk saya - penggunaan prosesor 0-1% alih-alih 10-20% untuk utas baca.

2) di baris HidDevice.cs #69 hapus:
//hasil pengembalian devicePath;
Ini akan memungkinkan untuk NativeMethods .SetupDiDestroyDeviceInfoList(deviceInfoSet); dipanggil dengan baik.
Selanjutnya, setelah NativeMethods .SetupDiDestroyDeviceInfoList(deviceInfoSet) tambahkan:
foreach (string devicePath di perangkat)
hasilkan kembali devicePath;
Ini akan memperbaiki kebocoran memori BESAR (sekitar 256MB untuk setiap 1MB data yang diterima dalam kasus saya)

Semoga heps.

luar biasa, terima kasih atas petunjuk Anda, kaczart!!!

Inilah solusi yang saya sarankan untuk masalah kinerja yang diperhatikan oleh kaczart (dan saya):
https://github.com/macaba/HidLibrary/commit/8f1864e1351ccca4772d5bbc18a0f94d7ba07fe7

Penggunaannya sejalan dengan:

device.ConnectionCheckOverride = device.IsConnected;
methodRequiringFasterUSBReadWrite();
device.ConnectionCheckOverride = false;

Ini mengurangi waktu eksekusi kasus uji transfer USB massal saya dari 159 detik menjadi 47 detik.

Saya tidak tertarik pada solusi kaczart hanya karena properti IsConnected digunakan di HidDeviceEventMonitor, jadi saya perlu mempertahankan fungsionalitas asli dari pencacahan perangkat USB yang saat ini terhubung. Sederhananya; Saya tidak berpikir acara yang Disisipkan dan Dihapus tidak akan pernah dipanggil dalam kode kaczart (dari tampilan singkatnya).

Memeriksa koneksi perangkat pada setiap baca dan tulis adalah hambatan kinerja utama dalam aplikasi frekuensi tinggi. Dalam kasus khusus saya, 30x lebih cepat untuk menganggap perangkat terhubung daripada memeriksa ulang koneksi perangkat; perjalanan pulang pergi turun dari sekitar 70 ms menjadi 2 ms.

Jadi saya baru saja menulis beberapa metode ekstensi untuk menangani IO saya sendiri untuk penggunaan pengumpulan cepat:

        [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;
            }
        }
Apakah halaman ini membantu?
0 / 5 - 0 peringkat