문제

방금 비대네크가 어떻게 구배를 돕는지와 나쁜 성능을 찾기 위해 놀랐을지를 볼 수있는 PERF 테스트 REDIS + GEVENT에 대한 간단한 코드를 썼습니다.여기 내 코드가 있습니다.원숭이 패치에 처음 두 줄을 제거하면이 코드가 "정상 실행"타이밍이 표시됩니다.

우분투 12.04 LTS VM, 나는 의 타이밍을보고있다.

원숭이 패치가없는

54 초 원숭이 패치와 함께 - 61 초

코드 / 접근 방식에 문제가 있습니까?여기에 PEF 문제가 있습니까?

#!/usr/bin/python

from gevent import monkey

monkey.patch_all()

import timeit
import redis
from redis.connection import UnixDomainSocketConnection

def UxDomainSocket():
    pool = redis.ConnectionPool(connection_class=UnixDomainSocketConnection, path =    '/var/redis/redis.sock')
    r = redis.Redis(connection_pool = pool)
    r.set("testsocket", 1)
    for i in range(100):
            r.incr('testsocket', 10)
    r.get('testsocket')
    r.delete('testsocket')


print timeit.Timer(stmt='UxDomainSocket()',
 setup='from __main__ import UxDomainSocket').timeit(number=1000)
.

도움이 되었습니까?

해결책

이것은 예상됩니다.

시스템 호출 비용이 실제 하드웨어보다 높은 VM 에서이 벤치 마크를 실행합니다. GEVENT가 활성화되면 더 많은 시스템 호출을 생성하는 경향이 있으므로 덜 성능을 덜받습니다.

스크립트의 스트레이스를 사용 하여이 시점을 쉽게 확인할 수 있습니다.

GEVENT가 없으면 내부 루프가 생성됩니다.

recvfrom(3, ":931\r\n", 4096, 0, NULL, NULL) = 6
sendto(3, "*3\r\n$6\r\nINCRBY\r\n$10\r\ntestsocket\r"..., 41, 0, NULL, 0) = 41
recvfrom(3, ":941\r\n", 4096, 0, NULL, NULL) = 6
sendto(3, "*3\r\n$6\r\nINCRBY\r\n$10\r\ntestsocket\r"..., 41, 0, NULL, 0) = 41
.

gevent를 사용하면 발생합니다 :

recvfrom(3, ":221\r\n", 4096, 0, NULL, NULL) = 6
sendto(3, "*3\r\n$6\r\nINCRBY\r\n$10\r\ntestsocket\r"..., 41, 0, NULL, 0) = 41
recvfrom(3, 0x7b0f04, 4096, 0, 0, 0)    = -1 EAGAIN (Resource temporarily unavailable)
epoll_ctl(5, EPOLL_CTL_ADD, 3, {EPOLLIN, {u32=3, u64=3}}) = 0
epoll_wait(5, {{EPOLLIN, {u32=3, u64=3}}}, 32, 4294967295) = 1
clock_gettime(CLOCK_MONOTONIC, {2469, 779710323}) = 0
epoll_ctl(5, EPOLL_CTL_DEL, 3, {EPOLLIN, {u32=3, u64=3}}) = 0
recvfrom(3, ":231\r\n", 4096, 0, NULL, NULL) = 6
sendto(3, "*3\r\n$6\r\nINCRBY\r\n$10\r\ntestsocket\r"..., 41, 0, NULL, 0) = 41
.

recvfrom 호출이 차단되면 (eazain) GEVent는 이벤트 루프로 돌아갑니다. 따라서 파일 설명자 이벤트 (EPOLL_WAIT)를 대기하기 위해 추가 호출이 수행됩니다.

이런 종류의 벤치 마크는 하나의 파일 설명 자만 있기 때문에 모든 이벤트 루프 시스템에 대한 최악의 경우이므로 대기 작업은 여러 설명자에서 인식 할 수 없습니다. 또한 모든 것이 동기식이기 때문에 비동기 I / O가 여기서 아무 것도 개선 할 수 없습니다.

Redis의 최악의 경우 :

  • 서버에 많은 왕복을 생성합니다

  • 풀이 UXDomastSocket 함수로 선언되기 때문에 저장 / 연결 해제를 체계적으로 연결 / 연결 해제합니다.

    실제로 벤치 마크는 GEVENT, REDIS 또는 REDIS-PY를 테스트하지 않습니다. VM의 능력을 2 프로세스간에 탁구 게임을 유지하는 능력을 연습합니다.

    성능을 높이려면 다음을 수행해야합니다.

    • 왕복 의 수를 줄이려면 파이프 라이닝을 사용하십시오.

    • 전체 벤치 마크를 통해 풀을 지속적으로 만드는

      예를 들어, 다음 스크립트를 고려하십시오.

      #!/usr/bin/python
      
      from gevent import monkey
      monkey.patch_all()
      
      import timeit
      import redis
      from redis.connection import UnixDomainSocketConnection
      
      pool = redis.ConnectionPool(connection_class=UnixDomainSocketConnection, path = '/tmp/redis.sock')
      
      def UxDomainSocket():
          r = redis.Redis(connection_pool = pool)
          p = r.pipeline(transaction=False)
          p.set("testsocket", 1)
          for i in range(100):
              p.incr('testsocket', 10)
          p.get('testsocket')
          p.delete('testsocket')
          p.execute()
      
      print timeit.Timer(stmt='UxDomainSocket()', setup='from __main__ import UxDomainSocket').timeit(number=1000)
      
      .

      이 스크립트를 사용하면 성능이 약 3 배 늘어나고 거의 오버 헤드가 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top