লিনাক্সের সর্বশেষ সংস্করণগুলিতে উচ্চতর টিসিপি লেটেন্সি


8

আমার গবেষণা গ্রুপে আমরা সম্প্রতি রেড হ্যাট 6.২ থেকে ডেবিয়ান ৮.৩ এ আমাদের মেশিনগুলিতে ওএস আপগ্রেড করেছি এবং লক্ষ্য করেছি যে আমাদের মেশিনগুলির মধ্যে সংহত ইন্টেল 1 জি এনআইসি-র মাধ্যমে টিসিপি রাউন্ড ট্রিপ সময় প্রায় 110µs থেকে 220µs দ্বিগুণ হয়েছে।

প্রথমে, আমি ভেবেছিলাম এটি একটি কনফিগারেশন সমস্যা, তাই আমি সমস্ত সিস্টেমে কনফিগারেশনগুলি (যেমন tcp_low_latency=1) আন-আপগ্রেড করা রেড হ্যাট মেশিন থেকে ডেবিয়ান মেশিনে অনুলিপি করেছিলাম এবং এটি সমস্যার সমাধান করেনি। এর পরে, আমি ভেবেছিলাম এটি লিনাক্স বিতরণ সমস্যা হতে পারে এবং মেশিনগুলিতে রেড হ্যাট 7.2 ইনস্টল করা থাকতে পারে তবে রাউন্ড ট্রিপ সময়টি প্রায় 220µ এর কাছাকাছি থেকে যায়।

অবশেষে, আমি বুঝতে পেরেছিলাম যে সমস্যাটি লিনাক্স কার্নেল সংস্করণগুলির সাথে ছিল কারণ ডেবিয়ান 8.3 এবং রেড হ্যাট 7.2 উভয়ই কার্নেল 3.x ব্যবহার করেছে যখন রেড হ্যাট 6.2 কার্নেল 2.6 ব্যবহার করেছে। সুতরাং এটি পরীক্ষা করার জন্য, আমি লিনাক্স কার্নেল ২.6 এবং বিঙ্গোর সাথে ডেবিয়ান .0.০ ইনস্টল করেছি! সময়গুলি আবার 110µs এ দ্রুত ছিল।

অন্যরাও কি লিনাক্সের সর্বশেষতম সংস্করণগুলিতে এই উচ্চতর বিলম্বকে অনুধাবন করেছে, এবং সেখানে কোনও কার্যকারিতা রয়েছে?


ন্যূনতম কাজের উদাহরণ

নীচে একটি সি ++ অ্যাপ্লিকেশন রয়েছে যা বিলম্বিতকরণের মানদণ্ডে ব্যবহার করা যেতে পারে। এটি কোনও বার্তা প্রেরণ, প্রতিক্রিয়ার অপেক্ষায় এবং তারপরে পরবর্তী বার্তা প্রেরণের মাধ্যমে বিলম্বের ব্যবস্থা করে। এটি 100-বাইট বার্তা সহ এটি 100,000 বার করে। এইভাবে, রাউন্ড ট্রিপ বিলম্ব পেতে আমরা ক্লায়েন্টের কার্যকরকরণের সময়কে 10,000,000 দিয়ে বিভক্ত করতে পারি। এই প্রথম প্রোগ্রামটি সংকলন ব্যবহার করুন:

g++ -o socketpingpong -O3 -std=c++0x Server.cpp

এর পরে একটি হোস্টে অ্যাপ্লিকেশনটির সার্ভার-পার্শ্বযুক্ত সংস্করণটি চালান (192.168.0.101 বলুন)। আমরা একটি সুপরিচিত ইন্টারফেসে হোস্টিং করছি তা নিশ্চিত করার জন্য আমরা আইপি নির্দিষ্ট করি।

socketpingpong 192.168.0.101

এবং তারপরে timeক্লায়েন্টের কার্যকরকরণের সময়টি পরিমাপ করতে ইউনিক্স ইউটিলিটিটি ব্যবহার করুন ।

time socketpingpong 192.168.0.101 client

অভিন্ন হার্ডওয়্যার সহ দুটি ডেবিয়ান 8.3 হোস্টের মধ্যে এই পরীক্ষা চালানো নীচের ফলাফলগুলি দেয়।

real  0m22.743s
user  0m0.124s
sys     0m1.992s

দেবিয়ান 6.0 ফলাফল

real    0m11.448s 
user    0m0.716s  
sys     0m0.312s  

কোড:

#include <unistd.h>
#include <limits.h>
#include <string.h>

#include <linux/futex.h>
#include <arpa/inet.h>

#include <algorithm>

using namespace std;

static const int PORT = 2444;
static const int COUNT = 100000;

// Message sizes are 100 bytes
static const int SEND_SIZE = 100;
static const int RESP_SIZE = 100;

void serverLoop(const char* srd_addr) {
    printf("Creating server via regular sockets\r\n");
    int sockfd, newsockfd;
    socklen_t clilen;
    char buffer[SEND_SIZE];
    char bufferOut[RESP_SIZE];
    struct sockaddr_in serv_addr, cli_addr;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
       perror("ERROR opening socket");

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(srd_addr);
    serv_addr.sin_port = htons(PORT);

    fflush(stdout);
    if (bind(sockfd, (struct sockaddr *) &serv_addr,
             sizeof(serv_addr)) < 0) {
             perror("ERROR on binding");
    }

    listen(sockfd, INT_MAX);
    clilen = sizeof(cli_addr);
    printf("Started listening on %s port %d\r\n", srd_addr, PORT);
    fflush(stdout);

    while (true) {
        newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
        if (newsockfd < 0)
             perror("ERROR on accept");
        printf("New connection\r\n");

        int status = 1;
        while (status > 0) {
            // Read
            status = read(newsockfd, buffer, SEND_SIZE);
            if (status < 0) {
                perror("read");
                break;
            }

            if (status == 0) {
                printf("connection closed");
                break;
            }

            // Respond
            status = write(newsockfd, bufferOut, RESP_SIZE);
            if (status < 0) {
                perror("write");
                break;
            }
        }

        close(newsockfd);
    }


    close(sockfd);
}

int clientLoop(const char* srd_addr) {
    // This example is copied from http://www.binarytides.com/server-client-example-c-sockets-linux/
    int sock;
    struct sockaddr_in server;
    char message[SEND_SIZE] , server_reply[RESP_SIZE];

    //Create socket
    sock = socket(AF_INET , SOCK_STREAM , 0);
    if (sock == -1)
    {
        printf("Could not create socket");
    }
    puts("Socket created");

    server.sin_addr.s_addr = inet_addr(srd_addr);
    server.sin_family = AF_INET;
    server.sin_port = htons( PORT );

    //Connect to remote server
    if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
    {
        perror("connect failed. Error");
        return 1;
    }

    printf("Connected to %s on port %d\n", srd_addr, PORT);

    // Fill buffer
    for (int i = 0; i < SEND_SIZE; ++i) {
        message[i] = 'a' + (i % 26);
    }

    for (int i = 0; i < COUNT; ++i) {
        if (send(sock, message, SEND_SIZE, 0) < 0) {
            perror("send");
            return 1;
        }

        if ( recv(sock, server_reply, RESP_SIZE, 0) < 0) {
            perror("recv");
            return 1;
        }
    }

    close(sock);

    printf("Sending %d messages of size %d bytes with response sizes of %d bytes\r\n",
            COUNT, SEND_SIZE, RESP_SIZE);
    return 0;
}

int main(int argc, char** argv) {
    if (argc < 2) {
        printf("\r\nUsage: socketpingpong <ipaddress> [client]\r\n");
        exit(-1);
    }
    if (argc == 2)
        serverLoop(argv[1]);
    else
        clientLoop(argv[1]);
    return 0;
}

2
রেডহাট থেকে ডিবিয়ান স্থানান্তরিত করার কারণ কী ছিল ? রেডহাট দিকে, এই জাতীয় সমস্যার মধ্য দিয়ে কাজ করতে আরও সরঞ্জাম এবং ইউটিলিটি রয়েছে।
ইয়েভাইট

1
আমি লিনাক্স কার্নেল মেলিং তালিকার সাথে যোগাযোগ করব বা আপনার যদি রেড হ্যাট সমর্থন থাকে contact তারা হয়ত জানতে পারে এবং যদি তারা না দেয় তবে বাগগুলি কোথা থেকে এসেছে তা খুঁজে বের করার জন্য কার্নেল কোড পরিবর্তন করতে সকলেই সেট আপ করা আছে।
Law29

আমি মনে করি আপনার কোডটি প্রোফাইল দেওয়ার জন্য আপনার কিছু সরঞ্জাম (জিপিআরফ, ভালগ্রাইন্ড বা গ্পারফটোল) ব্যবহার করা উচিত।
জোসে রাউল ব্যারারাস

আপনি যদি ক্লায়েন্ট / সার্ভার উভয় ক্ষেত্রে নাগলের অ্যালগরিদম অক্ষম করেন তবে কি হবে? int ndelay = 1; সেটসকোপ্ট (<সকেট>, আইপিপ্রোটো_সিটিপি, টিসিপি_নোডিলে, এবং পতাকা, মাপের (ইনট)); - পার্থক্য (গুলি) বজায় আছে? এছাড়াও - এটি কি কেবল টিসিপি-র জন্য? অর্থাত্ আইসিএমপি / পিংয়ের জন্য আপনি কি একই পর্যবেক্ষণ করেন?
কেজেটিল জোর্জেনসেন

1
এছাড়াও - "দ্রুত" এবং "ধীর" এর মধ্যে কোলেসেস বা অফলোড সেটিংসে কি কোনও পার্থক্য রয়েছে? ethtool -c <dev> এবং ethtool -k <dev>। ড্রাইভারের ডিফল্ট (গুলি) পরিবর্তিত হতে পারে।
কেজেটিল জোর্জেনসেন

উত্তর:


1

এটি কোনও উত্তর নয় তবে বিলম্বিতা / থ্রুপুট বিষয়গুলি কঠোরভাবে ক্যালিব্রেট করা গুরুত্বপূর্ণ important এটি আপনাকে উত্তরের নিকটবর্তী হতে এবং এখানকার অন্যদেরও আপনাকে শিকড় তৈরির প্রক্রিয়া সম্পর্কে আরও ভাল পরামর্শ দিতে সহায়তা করতে পারে।

একটি সঙ্গে আরো সঠিক তথ্য পাওয়ার চেষ্টা করুন wireshark ইন্টারফেস চালু / tshark ক্যাপচার,

  1. নিশ্চিত করুন যে থ্রুপুটটি আসলে অর্ধেক এবং
  2. কীভাবে প্রচ্ছন্নতা বিতরণ করা হয় তা চিহ্নিত করুন (tx এবং rx এর মধ্যে)
    ক। এটা কি পরীক্ষার উপর সমান?
    খ। কোথাও কোথাও একটি গলদা স্টল আছে?

0

আমি চেঞ্জলগগুলি দেখেছি, এটি সম্ভবত কিউএফকিউর ভূমিকা হতে পারে

কার্নেল 3.0 নেটওয়ার্কিং চেঞ্জলগ https://kernelnewbies.org/Linux_3.0#head-96d40fb6f9c48e789386dbe59fd5b5acc9a9059d

কিউএফকিউ প্রতিবেদকের পৃষ্ঠা http://info.iet.unipi.it/~luigi/qfq/

এটি প্রতি প্যাকেট ব্যয়ে অত্যন্ত স্বল্প পরিষেবার গ্যারান্টি সরবরাহ করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.