Heesung Yang

Linux Kernel Tuning

개념 잡기

  • tcp receive window size
    • 수신자가 한 번에 버퍼링할 수 있는 최대 데이터 크기(bytes)
    • 송신자는 수신자의 window size만큼 ACK를 기다리지 않고 데이터 송신 가능
    • ack 를 받기 전에 보낼 수 있는 패킷 수를 의미
    • tcp 는 ack 패킷을 받은 후에 다음 패킷을 보낼 수 있음
    • 이 값은 유동적으로 변경됨
    • ack 패킷을 timer 안에 수신할 경우 window size 늘림
    • 반대로 ack 패킷을 timer 안에 수신못할 경우 window size 줄임
    • 데이터 수신 측에서 buffer 가 꽉찰 경우 이를 송신측에 알림

Packet 수신

The NIC ring buffer

  • ring buffer 는 device driver 와 NIC 간에 공유함
  • NIC card 는 TX / RX ring buffer 를 할당함
  • ring buffer 는 circular buffer
    • overflow 발생 시 기존 data 를 덮어씀
  • NIC 에서 kernel 로 데이터를 가져오는 방법은 2가지
    • hardware interrupts
    • software interrupts ( SoftIRQs )
  • RX ring buffer 는 들어오는 packet을 (kernel driver 가 처리하기 전까지 ) 저장하는 용도임
  • kernel driver는 SoftIRQs 를 이용하여 ring buffer 로부터 packet 을 가져옴
    • ring buffer -> kernel data structure “sk_buff”
  • TX ring buffer 는 밖으로 나가는 packet 을 hold

Interrupts and Interrupt Handlers

  • NIC 가 packet 을 받으면 DMA를 이용하여 kernel buffer 로 복사함
  • NIC 는 kernel 에게 hardware interrupt 를 이용하여 알려줌
  • 이러한 interrupt 는 interrupt handler 에 의해 처리됨
  • as they have already interrupted another task and cannot be interrupted themselves
  • hard interrupt 는 CPU 를 많이 사용할 수 있음 ( 특히 when holding kernel locks )
  • hard interrupt 는 /proc/interrupts 에서 확인 가능 (1st column)
  • 이 값은 시스템 재부팅 또는 NIC driver load 시 초기화 됨

Interrupt coalescence

  • rx-frames : packet 을 얼마나 받은 후 rx interrupt 를 발생시킬 것인지 설정

  • rx-usecs : packet 을 받은 후 rx interrupt 를 발생시키기 전까지 기다리는 시간

    # IBM recommendation
    rx-frames : 5-10
    rx-usecs : 1-5
    
    # Oracle recommendation
    rx-frames : 512
    rx-usecs : 20
    rx-frames-irq : 512
    rx-usecs-irq : 0
    
  • 예를 들어 rx-usecs = 10, rx-frames = 100 일 경우 패킷 100개가 1 usec 안에 들어오면 interrupt 발생

  • 패킷 1개가 들어온 후 10 usecs 동안 더 이상 패킷이 안들어올 경우 interrupt 발생

  • 당연한 얘기지만 두 값을 증가시키면 interrupt 수가 줄어드므로 CPU 사용량 Down, 실시간성 Down

  • 변경 방법

    ~$ ethtool -C eth8 rx-usec 5
    ~$ ethtool -C eth8 rx-frames 10
    

RSS (Receive Side Scaling)

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/network-rss

RPS (Receive Packet Steering)

  • RSS 를 소프트웨어로 구현한 것

    ~$ cat /sys/class/net/eth8/queues/rx-0/rps_cpus
    00000000
    
    # cpu 1,2,3,4 코어 할당
    ~$ echo 2 > /sys/class/net/eth8/queues/rx-0/rps_cpus
    ~$ echo 4 > /sys/class/net/eth8/queues/rx-1/rps_cpus
    ~$ echo 8 > /sys/class/net/eth8/queues/rx-2/rps_cpus
    ~$ echo 10 > /sys/class/net/eth8/queues/rx-3/rps_cpus
    ~$ echo 2 > /sys/class/net/eth8/queues/rx-4/rps_cpus
    ~$ echo 4 > /sys/class/net/eth8/queues/rx-5/rps_cpus
    ~$ echo 8 > /sys/class/net/eth8/queues/rx-6/rps_cpus
    ~$ echo 10 > /sys/class/net/eth8/queues/rx-7/rps_cpus
    ~$ echo 2 > /sys/class/net/eth8/queues/rx-8/rps_cpus
    ~$ echo 4 > /sys/class/net/eth8/queues/rx-9/rps_cpus
    ~$ echo 8 > /sys/class/net/eth8/queues/rx-10/rps_cpus
    ~$ echo 10 > /sys/class/net/eth8/queues/rx-11/rps_cpus
    ~$ echo 2 > /sys/class/net/eth8/queues/rx-12/rps_cpus
    ~$ echo 4 > /sys/class/net/eth8/queues/rx-13/rps_cpus
    ~$ echo 8 > /sys/class/net/eth8/queues/rx-14/rps_cpus
    ~$ echo 10 > /sys/class/net/eth8/queues/rx-15/rps_cpus
    
  • 큐 개수는 아래 명령어로 확인 및 변경 가능

    # 변경 전 큐 개수 : 32
    ~$ ethtool -l eth8
    Channel parameters for eth8:
    Pre-set maximums:
    RX:     0
    TX:     0
    Other:      1
    Combined:   63
    Current hardware settings:
    RX:     0
    TX:     0
    Other:      1
    Combined:   32
    
    # 큐 개수 16개로 변경
    # 변경 시 smp_affinity 설정이 무효화 되므로 재설정 필요
    ~$ ethtool -L eth8 combined 16
    
    # 변경된 큐 개수는 /proc/interrupts 에서도 확인 가능
    # 변경 후 큐 개수 : 16
    ~$ ethtool -l eth8
    Channel parameters for eth8:
    Pre-set maximums:
    RX:     0
    TX:     0
    Other:      1
    Combined:   63
    Current hardware settings:
    RX:     0
    TX:     0
    Other:      1
    Combined:   16
    
  • tx/rx 큐가 따로 있을 경우 /proc/interrupts 파일에서 eth8-rx-0 / eth8-tx-0 으로 보임

  • 큐가 분리되어 있어야 ethtool -L 명령어로 RX/TX 큐 개수를 각각 지정할 수 있음

  • 분리 안되어 있을 경우 eth8-TxRx-14 처럼 보임

커널 설정

  • net.core.dev_weight = 64
    • queue drain rate

Context Switch

  • voluntary context switch : 사용할 수 없는 자원을 요청해서 task 가 block 될 경우 발생
  • involuntary context switch : 주어진 cpu time 을 모두 사용했을 경우 발생

Numa 아키텍쳐에서의 Large Memory 사용 시 알아야 할 것

참고 사이트

~$ ethtool -X eth8 weight 0 1 1 1 1
RX flow hash indirection table for eth8 with 16 RX ring(s):
    0:      1     1     1     1     1     1     1     1
    8:      1     1     1     1     1     1     1     1
   16:      1     1     1     1     1     1     1     1
   24:      1     1     1     1     1     1     1     1
   32:      2     2     2     2     2     2     2     2
   40:      2     2     2     2     2     2     2     2
   48:      2     2     2     2     2     2     2     2
   56:      2     2     2     2     2     2     2     2
   64:      3     3     3     3     3     3     3     3
   72:      3     3     3     3     3     3     3     3
   80:      3     3     3     3     3     3     3     3
   88:      3     3     3     3     3     3     3     3
   96:      4     4     4     4     4     4     4     4
  104:      4     4     4     4     4     4     4     4
  112:      4     4     4     4     4     4     4     4
  120:      4     4     4     4     4     4     4     4

Previous post

[명령어] rpm

Next post

Docker