Best practice of eBCC performance analysis - a simple eBCC analysis network function's latency

Keywords: Linux socket network

0. Intro

BCC is a set of performance analysis tools based on ebpf of 4.x kernel;

eBCC, as the name implies, is the abbreviation of extended BCC. It is the extension of the BCC project by Alibaba kernel team on Aliyun Linux, including the existing tool set of BCC itself and some small tools newly developed by us. eBCC is based on the extension of the latest BCC version 0.9.

Aliyun Linux uses a relatively cutting-edge, newer kernel version that supports ebpf features. So if you want to try ebpf and the new experience of "performance optimization debugging" and "problem diagnosis" brought by eBCC, please upgrade to aliyun Linux as soon as possible.

1. Establish tcp link and analyze latency

scene

  1. Establishing tcp link and analyzing latency of network function
  2. Statistics of tcp transmission, send, recv times and latency

client

Monitoring when the client initiates the connect link

/usr/share/ebcc/tools/tcpconnect

server

Monitoring of server accept

/usr/share/ebcc/tools/tcpaccept

client latency

client initiates the latency of connect()

/usr/share/ebcc/tools/tcpconnlat

2. Statistics of TCP transmission, send, recv times and latency

client send latency

Client: 

[root@xxx /home/ahao.mah/socket]
#./client1
hello muahao
^@

Server: 

[root@xxx /home/ahao.mah/socket]
#./server1

latency:

[root@xxx ]
#/usr/share/ebcc/tools/funclatency -i 1 c:send  -p 65035
Tracing 1 functions for "c:send"... Hit Ctrl-C to end.
     nsecs               : count     distribution
         0 -> 1          : 0        |                                        |
         2 -> 3          : 0        |                                        |
         4 -> 7          : 0        |                                        |
         8 -> 15         : 0        |                                        |
        16 -> 31         : 0        |                                        |
        32 -> 63         : 0        |                                        |
        64 -> 127        : 0        |                                        |
       128 -> 255        : 0        |                                        |
       256 -> 511        : 0        |                                        |
       512 -> 1023       : 0        |                                        |
      1024 -> 2047       : 0        |                                        |
      2048 -> 4095       : 0        |                                        |
      4096 -> 8191       : 0        |                                        |
      8192 -> 16383      : 0        |                                        |
     16384 -> 32767      : 1        |****************************************|

Example

Client:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>

#define MYPORT  8887
#define BUFFER_SIZE 1024
#define DST_IP "10.137.16.6"

int main()
{
    ///Define sockfd
    int sock_cli = socket(AF_INET,SOCK_STREAM, 0);

    ///Define SOCKADDR? In
    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(MYPORT);  ///Server port
    servaddr.sin_addr.s_addr = inet_addr(DST_IP);  /// server ip

    ///Connect to the server, 0 for success and - 1 for error
    if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
    {
        perror("connect");
        exit(1);
    }

    char sendbuf[BUFFER_SIZE];
    char recvbuf[BUFFER_SIZE];
    while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
    {
        send(sock_cli, sendbuf, strlen(sendbuf),0); /// send
        if(strcmp(sendbuf,"exit\n")==0)
            break;
        recv(sock_cli, recvbuf, sizeof(recvbuf),0); /// reception
        fputs(recvbuf, stdout);

        memset(sendbuf, 0, sizeof(sendbuf));
        memset(recvbuf, 0, sizeof(recvbuf));
    }

    close(sock_cli);
    return 0;
}

Server:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>

#define MYPORT  8887
#define QUEUE   20
#define BUFFER_SIZE 1024

int main()
{
    ///Define sockfd
    int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);

    ///Define SOCKADDR? In
    struct sockaddr_in server_sockaddr;
    server_sockaddr.sin_family = AF_INET;
    server_sockaddr.sin_port = htons(MYPORT);
    server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    ///bind, return 0 successfully, return - 1 in error
    if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)
    {
        perror("bind");
        exit(1);
    }

    ///listen, 0 returned successfully, 1 returned in error
    if(listen(server_sockfd,QUEUE) == -1)
    {
        perror("listen");
        exit(1);
    }

    ///Client socket
    char buffer[BUFFER_SIZE];
    struct sockaddr_in client_addr;
    socklen_t length = sizeof(client_addr);

    ///Non negative description word returned successfully, error returned - 1
    int conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length);
    if(conn<0)
    {
        perror("connect");
        exit(1);
    }

    while(1)
    {
        memset(buffer,0,sizeof(buffer));
        int len = recv(conn, buffer, sizeof(buffer),0);
        if(strcmp(buffer,"exit\n")==0)
            break;
        fputs(buffer, stdout);
        send(conn, buffer, len, 0);
    }
    close(conn);
    close(server_sockfd);
    return 0;
}

Posted by cristiano on Fri, 29 Nov 2019 11:55:34 -0800