Hidlibrary: تسرب ذاكرة ReadReport ()

تم إنشاؤها على ١٤ أغسطس ٢٠١١  ·  9تعليقات  ·  مصدر: mikeobrien/HidLibrary

مكتبة كبيرة مايك ، شكرا جزيلا على هذا العمل الضخم.

المشكلة هي عندما أرغب في ملء InputReport بالبيانات:

InputReport = device.ReadReport () ،

حيث يكون InputReport هو:

HidLibrary.HidReport InputReport = new HidLibrary.HidReport (device.Capabilities.InputReportByteLength) ؛

إنها ذاكرة كبيرة جدًا من التسرب ، خاصة عندما أقرأ التقارير في وضع غير متزامن من الجهاز (على سبيل المثال 100 مرة في الثانية). في غضون دقائق قليلة يمكن أن يستغرق الأمر مئات الميجابايت.

أنا مبتدئ في برمجة c # ولم أجد حلًا للمشكلة الموضحة أعلاه ؛ (

تحية طيبة!

التعليق الأكثر فائدة

إليكم الحل الذي اقترحه لمشكلة الأداء التي لاحظها كاكزارت (وأنا):
https://github.com/macaba/HidLibrary/commit/8f1864e1351ccca4772d5bbc18a0f94d7ba07fe7

الاستخدام على غرار:

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

أدى ذلك إلى تقليل وقت تنفيذ حالة اختبار نقل USB بالجملة من 159 ثانية إلى 47 ثانية.

لم أكن حريصًا على حل kaczart لمجرد أن خاصية IsConnected مستخدمة في HidDeviceEventMonitor ، لذا يلزم الاحتفاظ بالوظيفة الأصلية لتعداد أجهزة USB المتصلة حاليًا. ببساطة؛ لا أعتقد أنه سيتم استدعاء الأحداث المدرجة والإزالة في رمز kaczart (من نظرة مختصرة عبرها).

ال 9 كومينتر

كازارت ،

لسوء الحظ ، هذا الرمز قديم جدًا ولم يكن لدي الوقت لإعطائه
أي TLC. في هذه المرحلة لدي فقط كمرجع. افضل ما عندك
الرهان هو شوكة / تحسين.

م

يوم الأحد 14 أغسطس 2011 الساعة 10:37 صباحًا ، kaczart <
[email protected]> كتب:

مكتبة كبيرة مايك ، شكرا جزيلا على هذا العمل الضخم.

المشكلة هي عندما أرغب في ملء InputReport بالبيانات:

InputReport = device.ReadReport () ،

حيث يكون InputReport هو:

HidLibrary.HidReport InputReport = جديد
HidLibrary.HidReport (ukp.Capabilities.InputReportByteLength) ،

إنها ذاكرة تسرب كبيرة جدًا ، خاصةً عندما أقرأ التقارير غير المتزامنة
الوضع من الجهاز (على سبيل المثال 100 مرة في الثانية). يمكن في دقائق قليلة
يستغرق مئات الميجابايت.

أنا مبتدئ في برمجة c # ولم أجد حلًا للمشكلة
desrcibed أعلاه ؛ (

تحية طيبة!

قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub:
https://github.com/mikeobrien/HidLibrary/issues/11

كازارت ،

هل وجدت حل؟ أنا فقط لاحظت نفس الشيء.
مكتبة كبيرة مايك ، شكرا جزيلا لك! أنا أعمل بميزان USB Endicia وهذا ممتع للغاية.

jrockfl

للأسف لم يكن لدي وقت ولا مهارة كافية لإصلاح هذه المشكلة :(

تحية طيبة

المشكلة هي أن HidReport و Devicedata لم يتم تحريرهما ، لذلك ينتظر جمع القمامة.
إنه حل سهل على الرغم من إطلاقه بعد معالجته ...

أخيرًا ، اضطررت إلى إصلاح هذه المشكلة وأشارك ما وجدته

1) أولاً وقبل كل شيء ، تتحقق كل طرق قراءة / كتابة في المكتبة مما إذا كان الجهاز متصلاً ما يكلف الكثير من الأداء لأن طريقة IsConnected تستدعي في كل مرة EnumerateHidDevices (). من الناحية العملية ، عندما أرسل حزمة كبيرة من البيانات من الجهاز ، يكون مضيف الكمبيوتر أبطأ من جهاز HID ويتم فقد بعض الحزم بسبب محدودية المخزن المؤقت للحلقة (32 تقريرًا افتراضيًا ، يمكن تمديدها إلى 512 ولكنها ليست الحل النهائي).
ملاحظة. يمكنك تمديد المخزن المؤقت للحلقة من 32 إلى 512 تقريرًا كحد أقصى للاتصال:
NativeMethods .HidD_SetNumInputBuffers ((int) device.ReadHandle، 512) ؛ // ستعمل مع XP والإصدارات الأحدث.
2) ثانيًا ، في EnumerateHidDevices () هو تسرب كبير للذاكرة بسبب "إنتاج مسار الجهاز المرتجع ؛" في السطر 69 و NativeMethods.SetupDiDestroyDeviceInfoList (deviceInfoSet) ؛ لن يتم استدعاؤها.

بلدي الحل:
1) لا تتصل بـ IsConnected كل قراءة / كتابة. عمل متغير isConnected إضافي في HidDevice:
المنطقية العامة متصلة ؛
اضبط المتغير على true بعد الاتصال الناجح (على سبيل المثال في وظيفة Connect ()):
device.isConnected = صحيح ؛
قم بتحديثه في كل حدث DeviceEventMonitorInserted () و DeviceEventMonitorRemoved () ، على سبيل المثال:
إذا (مُدرج! = فارغ) مُدرج () ؛
استبدل ب:
إذا (مُدرج! = فارغ)
{
غير متصل = صحيح ؛
إدراج () ؛
}
و:
إذا (تمت إزالته! = فارغة) تمت إزالته () ؛
استبدل ب:
إذا (تمت إزالته! = فارغ)
{
غير متصل = خطأ ؛
إزالة()؛
}
من التحقق من هذا المتغير في كل وظيفة استدعاء قراءة / كتابة:
إذا (غير متصل) بدلاً من إذا (متصل)
في كل مرة تريد التحقق مما إذا كان الجهاز متصلاً ، تحقق من حالة المتغير العام متصل. إنه يعمل بالنسبة لي - 0-1٪ استخدام المعالج بدلاً من 10-20٪ لقراءة الموضوع.

2) في HidDevice.cs سطر # 69 ، احذف:
// العائد جهاز المسار ؛
سيسمح لـ NativeMethods .SetupDiDestroyDeviceInfoList (deviceInfoSet) ؛ أن يتم استدعاؤهم بشكل لائق.
بعد ذلك ، بعد NativeMethods .SetupDiDestroyDeviceInfoList (deviceInfoSet) ، أضف:
foreach (سلسلة devicePath في الأجهزة)
جهاز العائد العائد
سيعمل على إصلاح تسرب الذاكرة الضخم (حوالي 256 ميجابايت لكل 1 ميجابايت من البيانات المستلمة في حالتي)

اتمنى ان يكون.

رائع ، شكرا لتلميحاتك ، kaczart !!!

إليكم الحل الذي اقترحه لمشكلة الأداء التي لاحظها كاكزارت (وأنا):
https://github.com/macaba/HidLibrary/commit/8f1864e1351ccca4772d5bbc18a0f94d7ba07fe7

الاستخدام على غرار:

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

أدى ذلك إلى تقليل وقت تنفيذ حالة اختبار نقل USB بالجملة من 159 ثانية إلى 47 ثانية.

لم أكن حريصًا على حل kaczart لمجرد أن خاصية IsConnected مستخدمة في HidDeviceEventMonitor ، لذا يلزم الاحتفاظ بالوظيفة الأصلية لتعداد أجهزة USB المتصلة حاليًا. ببساطة؛ لا أعتقد أنه سيتم استدعاء الأحداث المدرجة والإزالة في رمز kaczart (من نظرة مختصرة عبرها).

يعد التحقق من اتصال الجهاز عند كل قراءة وكتابة عقبة رئيسية في الأداء في التطبيقات عالية التردد. في حالتي الخاصة ، كان من الأسرع بـ 30 مرة افتراض أن الجهاز متصل بدلاً من إعادة التحقق من اتصال الجهاز ؛ انخفضت الرحلات ذهابًا وإيابًا من حوالي 70 مللي ثانية إلى 2 مللي ثانية.

لذلك كتبت للتو طريقتين إضافيتين للتعامل مع الإدخال / الإخراج الخاص بي لاستخدام التجميع السريع:

        [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;
            }
        }
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات