لماذا هي وظيفة "CAT" الخاصة بي مع مكالمات النظام أبطأ مقارنة مع "Cat" Linux؟

StackOverflow https://stackoverflow.com/questions/769550

  •  12-09-2019
  •  | 
  •  

سؤال

لقد فعلت هذه الوظيفة في C باستخدام مكالمات النظام (فتح، قراءة والكتابة) لمحاكاة وظيفة "Cat" في أنظمة Linux وهي أبطأ من واحد حقيقي ...

أنا أستخدم نفس الحجم المخزن المؤقت مثل "القط" الحقيقي واستخدام "الستر" وأعتقد أنه يجعل نفس الكمية من مكالمات النظام. لكن الإخراج من "القط" هو أبطأ قليلا من "القط" الحقيقي.

هذا هو الرمز الذي لدي:

#define BUFSIZ 32768

int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) {
    ssize_t writtenBytes = 0;

    while(writtenBytes < readBytes) {
        writtenBytes += write(fdout,
            buffer + writtenBytes, readBytes - writtenBytes);
        if(writtenBytes == -1) {
            return -1;
        }
    }

    return 0;
}

int catPrint(int fdin, int fdout) {
    char buffer[BUFSIZ];
    ssize_t readBytes;

    do {
        readBytes = read(fdin, buffer, BUFSIZ);

        if(readBytes == -1) {
            return -1;
        }

        if(sysWriteBuffer(fdout, buffer, readBytes) == -1) {
            return -1;
        }
    } while(readBytes > 0);

    return 0;
}

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

لا أفهم لماذا تبدو أبطأ لأنني أستخدم نفس الملف لاختبار ومع كلا (القط "القائم الحقيقي" والألغام) هناك فقط قراءة واحدة () وكتابة واحدة () للنص بأكمله. لا ينبغي أن تظهر النص بأكمله على الشاشة؟

ملاحظة: لقد وصفت بهذا كواجب منزلي رغم أن سؤالي هنا (لماذا يبطء) ليس جزءا من الواجبات المنزلية. كنت بحاجة فقط لاستخدام مكالمات النظام لإنشاء وظيفة نوع "CAT"، والتي يتم ذلك. أنا فقط مفتون من رمزي هذا أبطأ قليلا.

مشكلة حل مع الغباء مني:
قررت للتو استدعاء القط الأصلي لينكس عدة مرات في نفس الملف، واحدا تلو الآخر، وأدركت فقط أنه كان بطيئا أيضا بعض الأوقات التي اتصلت بها، بطيئة مثل بلدي. أعتقد أن كل شيء على ما يرام من ...

آسف لإضاعة وقتك مثل هذا الناس.

هل كانت مفيدة؟

المحلول

آه، بناء على تحرير الخاص بك كنت عضك من قبل المخزن المؤقت Readhead. لا يمكنك اختبار برامجين تقرأ الملفات جنبا إلى جنب عن طريق تشغيلها مرة واحدة. الأول دائما يكون أبطأا نظرا لأن الملف موجود على القرص، بمجرد أن يكون الملف في الذاكرة، سيتم تشغيل الثانية بشكل أسرع، يجب عليك إما إنشاء بيانات جديدة لكل أو تشغيل واحدة ثم قم بتشغيل كلاهما حتى يحصلوا على فائدة من المخزن المؤقت Readhead.

نصائح أخرى

البحث MMAP (2).

سوف ترمي Niceties من FTELL / FORED، لكنها ستتخطي طبقة من عدم الإنارة إذا كانت الإنتاجية في القراءة مهمة حقا.

ربما كنت قد تم تجميعها دون تحسين (أو دون ارتفاع إعداد تحسين)؟

أيضا، سيتصل الرمز الخاص بك sysWriteBuffer مرة واحدة مع readBytes يساوي الصفر - ربما هذا (جزئيا) يفسر ذلك؟

قد تضمنت أيضا SyswriteBuffer (إما عبر مفتاح مترجم أو باليد).

"ملطخ" يعني نسخ جسم وظيفة إلى موقع استدعاءه من أجل إزالة النفقات العامة لاستدعاء وظيفة. في بعض الأحيان يقوم المترجمون في القيام بذلك تلقائيا (أعتقد أن -O3 يتيح هذا التحسين في دول مجلس التعاون الخليجي). يمكنك أيضا استخدام inline الكلمة الرئيسية في مجلس التعاون الخليجي لإخبار المحول البرمجي بإنشاء وظيفة. إذا قمت بذلك، فستبدو إعلانك مثل هذا:

static inline int sysWriteBuffer(int fdout, char *buffer, ssize_t readBytes) {
....

دون مقارنة رموز المصدر، من الصعب القول. إذا كنت تقارن القط الخاص بك مع قطة جنو، تذكر أنك تقارن رمز بضع ساعات / أيام قديمة مع رمز تطورت لأكثر من عشرين عاما.

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

نظرا لأن القط نفسها تافهة حقا (وأنت قلت في تعليق أنك تقوم بالفعل بتحسين التجميع)، فأنا أراهن أن تأثير الأداء الذي تراقبه ليس في الخوارزمية الفعلية، ولكن على أوقات تحميل البرنامج. إذا كان النظام ثنائي هو prelinked. (وهو أمر شائع في معظم distros الآن)، سترى أنه يتم تحميله بشكل أسرع من أي برنامج تقوم بتجميعه بنفسك (حتى تضمين برامجك

كم الثمن؟ القط الكنسي هو شيء مثل

char bufr[BUFSIZ];
ssize_t len;

while((len=read(fdin, bufr, BUFSIZ)) >0)
     write(fdout, bufr, len);

الذي يحفظ بعض التعليمات.

هل قارنت straceق كلاهما؟ قد تحاول استخدام -tt المعلمة حتى تحصل على توقيت syscalls.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top