[REDIS] 레디 스 + gevent을 - 성능이 저하 - 내가 잘못 뭐하는 거지?
REDIS레디 스 + gevent을 - 성능이 저하 - 내가 잘못 뭐하는 거지?
난 그냥 비동기가 perforamance을하는 데 도움이 나는 나쁜 성능을 찾기 위해 놀랐다 방식을 볼 수 반환 한 테스트 레디 스 +의 gevent에 코드의 간단한 조각을 썼다. 여기에 내 코드입니다. 당신은 원숭이 패치에 처음 두 줄의 코드를 제거하는 경우에 당신은 "정상적인 실행"타이밍을 볼 수 있습니다.
우분투 12.04 LTS VM에, 나는의 타이밍을보고 있어요
원숭이 패치없이 - 54 초 원숭이 패치 - 61초
내 코드 / 접근이 뭔가 잘못인가? 반환 한 문제가 있나요?
#!/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)
해결법
-
==============================
1.이는 예상된다.
이는 예상된다.
당신은 시스템 호출의 비용이 물리적 하드웨어에보다 높은에서 VM에이 벤치 마크를 실행합니다. gevent가 활성화되면, 당신이 적은 성능을 끝낼 수 있도록, (epoll 파일 장치를 처리하는) 더 많은 시스템 호출을 생성하는 경향이있다.
당신은 쉽게 스크립트에 strace를 사용하여이 점을 확인할 수 있습니다.
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 호출 (EAGAIN) 차단되면, gevent 때문에 추가 호출이 파일 기술자 이벤트 (에 epoll_wait)를 기다려야 완료, 다시 이벤트 루프로 간다.
당신은 단지 하나의 파일 디스크립터를 가지고 있기 때문에 대기 작업이 여러 기술자에 인수 분해 할 수 없도록 벤치 마크 이런 종류의, 어떤 이벤트 루프 시스템에 대한 최악의 경우가 있습니다. 모든 동기이기 때문에 또한, I 비동기 / O를 여기에 아무것도 개선되지 수 있습니다.
또한 레디 스 때문에위한 최악의 경우입니다 :
실제로 벤치 마크는하지 테스트 gevent을 수행 레디 스 또는 레디 스-평 : 그것은 두 프로세스 사이의 탁구 게임을 유지하기 위해 VM의 기능을 행사한다.
당신이 성능을 향상하려면 다음을 수행해야합니다
예를 들어, 다음 스크립트를 고려 :
#!/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)
이 스크립트, 나는 gevent 거의 오버 헤드 3 배 성능 향상에 대해 얻을합니다.
from https://stackoverflow.com/questions/10656953/redis-gevent-poor-performance-what-am-i-doing-wrong by cc-by-sa and MIT license
'REDIS' 카테고리의 다른 글
[REDIS] 레디 스 키 내에서 콜론의 목적은 무엇인가 (0) | 2020.01.11 |
---|---|
[REDIS] 어떻게 레디 스와 비활성화 지속성? (0) | 2020.01.10 |
[REDIS] 어떻게 다른 컴퓨터에서 복사 스냅 샷 (RDB 파일)에서 레디 스 데이터를 복구하려면? (0) | 2020.01.10 |
[REDIS] 127.0.0.1:6379에서 레디 스에 연결할 수 없습니다 : 연결 사제와 거부 (0) | 2020.01.10 |
[REDIS] 연관 배열을 저장하는 방법 레디 스? 설정 또는 해시 또는 목록? (0) | 2020.01.10 |