Avatar billede stringbuffer Nybegynder
04. juni 2002 - 13:03 Der er 4 kommentarer og
1 løsning

send til socket: FreeBSD vs. Linux

Jeg er blevet meget overrasket over at FreeBSD, som ellers lader til at køre hurtigere end Linux mht. alle andre ting, tilsyneladende er meget langsommere/dårligere end Linux når det drejer sig om at sende til en TCP socket.

Jeg har lavet et lille benchmark program, som bare er en primitiv server, der sender så mange gange, den kan, når der etableres forbindelse (med telnet). Programmet viser hvor mange gange der bliver sendt før sendbufferen fyldes op og hvor lang tid det tager.

Programmet er kørt på PC med følgende hardware:
Bundkort: ECS K7S5A
RAM: 256 MB PC133
CPU: AMD Duron 900 MHz
NIC: RealTek 8139 baseret PCI Ethernet kort (fra Zonet)
FreeBSD installeret på Seagate Barracuda IV (40 GB 7200 RPM)
Linux installeret på en 20 GB 5400 RPM disk fra Seagate

Her er programmet:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/select.h>

#define TIME_DIFFERENCE(t2, t1) (int)((t2.tv_sec-t1.tv_sec)*1000000 + t2.tv_usec-t1.tv_usec)

void fail(const char* msg)
{
    perror(msg);
    exit(1);
}

void sigpipe_handler(int code)
{
    printf("Sigpipe. Code: %d\n", code);
}

int main(void)
{
    fd_set master, rfds;
    struct sockaddr_in myaddr, remoteaddr;
    struct timeval before, after;
    int listener, sockfd, saveflags, yes=1, i, j, n;
    char buf[256];
    const long sndbufsize = 65536;
   
    signal(SIGPIPE, sigpipe_handler);
   
    if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    fail("socket");
       
    if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
    fail("setsockopt");
   
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = INADDR_ANY;
    myaddr.sin_port = htons(1027);
    memset(&(myaddr.sin_zero), '\0', 8);

    if (bind(listener, (struct sockaddr *)&myaddr, sizeof(struct sockaddr)) == -1)
            fail("bind");
    if (listen(listener, 10) == -1)
        fail("listen");
           
    FD_ZERO(&master);
    FD_SET(listener, &master);
                       
    while (1)
    {
    rfds = master;
    if (select(listener+1, &rfds, NULL, NULL, NULL) < 0)
        fail("select()");
   
    if (gettimeofday(&before, NULL) != 0)
        fail ("gettimeofday()");
   
    if (FD_ISSET(listener, &rfds))
    {
        if ((sockfd = accept(listener, NULL, 0)) == -1)
                fail("accept");
            saveflags = fcntl(sockfd,F_GETFL,0);
            if(saveflags < 0)
                fail("fcntl1");
            if(fcntl(sockfd, F_SETFL, saveflags|O_NONBLOCK) < 0)
                fail("fcntl2");
            if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (void*)&sndbufsize, (socklen_t)sizeof(int)) < 0)
                fail("setsockopt()");
    }
    i = sprintf(buf, "Hejsa! Det er idag et vejr, et solskinsvejr... din socket har nummer %d\r\n", sockfd);
    for (j=0; j<10000; j++)
    {
        //n = write(sockfd, buf, i);
        n = send(sockfd, buf, i,0);
        if (n < i)
        {
        perror("send()");
        break;
        }
    }
    if (gettimeofday(&after, NULL) != 0)
        fail ("gettimeofday()");
    printf("send() kaldt %d gange\nTid: %d usec\n", j, TIME_DIFFERENCE(after, before));
    close(sockfd);
    }
    return 0;
}

(oversættes med gcc på begge OS)

Og her er resultater af testkørsel:

RedHat Linux 7.2 (Kerne 2.4.17):

send(): Success
send() kaldt 1501 gange
Tid: 3555 usec
send(): Illegal seek
send() kaldt 1501 gange
Tid: 4944 usec
send(): Illegal seek
send() kaldt 1501 gange
Tid: 3233 usec
send(): Illegal seek
send() kaldt 1501 gange
Tid: 3279 usec
send(): Illegal seek
send() kaldt 1501 gange
Tid: 3301 usec

(gennemsnit: 2.4 ms pr. 1000 linier)


FreeBSD 4.5

send(): Resource temporarily unavailable
send() kaldt 972 gange
Tid: 6854 usec
send(): Resource temporarily unavailable
send() kaldt 931 gange
Tid: 6145 usec
send(): Resource temporarily unavailable
send() kaldt 972 gange
Tid: 6973 usec
send(): Resource temporarily unavailable
send() kaldt 972 gange
Tid: 6929 usec
send(): Resource temporarily unavailable
send() kaldt 931 gange
Tid: 6482 usec

(gennemsnit: 6.8 ms pr. 1000 linier)


FreeBSD er altså knap 3 gange så lang tid om at udføre det samme.

Hvad skyldes det?
Kan man tune FreeBSD til samme performance som Linux? Hvordan?
Avatar billede fpnovell Nybegynder
06. juni 2002 - 00:23 #1
Jeg synes, at du skulle se på disse link

http://www.byte.com/documents/s=1794/byt20011107s0001/1112_moshe.html

hvor Linux-kernen 2.4.10 testes imod FreeBSD 4.3 fra november 2001.
I januar ti måneder tidligere foretog han en lignende test med FreeBSD 4.1.1 imod Linux-kernen 2.4: http://www.byte.com/documents/s=558/byt20010130s0010/index.htm

Jo, det er absolut muligt at gøre FreeBSD signifikant hurtigere - bl.a. via aktivering af softupdates i filsystemet og forøgelse af maxusers værdien samt deaktivering af timestamping for inodes.

Om det vil give den samme performance kan kun en prøve afgøre. Forskelligt hardware vil muligvis give forskellige resultater, som han også skriver.
Og hvad det nøjagtig skyldes, kræver sandsynligvis en ret videnskabelig og kompliceret forklaring - som jeg ikke kan give. Der skal man nok have fat i de såkaldte kernel-hackere for at få en forklaring.

Mandens baggrund giver i øvrigt hans ord en vis vægt!

mvh
fpnovell
Avatar billede stringbuffer Nybegynder
06. juni 2002 - 11:38 #2
Den kerne, jeg har testet FreeBSD med, har jeg lavet med maxusers sat til 256 og NMBCLUSTERS til over 100.000 - softupdates kører også, selvom de ikke har noget at gøre med netværks sockets.

Jeg har også prøvet med kerne fra CD'en inden jeg lavede min egen, den kørte dog endnu dårligere...
Avatar billede stringbuffer Nybegynder
06. juni 2002 - 11:49 #3
Jeg har iøvrig læst en af de benchmarks, han lavede, inden du sendte linket, men jeg fandt det ubrugeligt, da han ikke skriver noget om ydeevnen, der er forbundet med brugen af TCP primitives på de 2 OS typer.
Avatar billede stringbuffer Nybegynder
06. juni 2002 - 11:50 #4
...og som sagt var det samme hardware (disken er ligegyldig, det er cirka den samme og den bruges slet ikke under kørsel af mit prog)
Avatar billede stringbuffer Nybegynder
24. november 2002 - 13:20 #5
Lukker, FreeBSD har åbenbart en dårligere TCP/IP implementation end Linux
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester