2010-04-08 2 views
2

나는 여러 guids를 생성하고 네트워크를 통해 다른 데이터를 클라이언트에 되돌려 주어야하는 파이썬 프로그램을 가지고있다. 짧은 시간 내에 많은 요청이있을 수 있으며 지연 시간을 가능한 한 적게하고 싶습니다.파이썬에서 사용할 GUID를 미리 생성 하시겠습니까?

이상적으로 클라이언트가 응답을 기다릴 때마다 새로운 guids를 생성하는 것이 아니라 항상 내가 미리 생성 된 것들을 준비 할 수 있도록 지속적으로 보충되는 백그라운드에서 guid 목록을 대량 생성하는 것이 좋습니다 나눠주기.

저는 리눅스에서 파이썬으로 uuid 모듈을 사용하고 있습니다. uuidd 데몬을 사용하여 uuids를 사용하고 있음을 이해합니다. uuidd는 이미 사전 배설물을 관리하므로 항상 준비가되어 있습니까? 설명서에서는 그렇지 않은 것으로 보입니다.

파이썬 또는 uuidd에서 자동으로이 작업을 수행 할 수있는 설정이 있습니까? 좀 더 우아한 방법이 있습니까? 그러면 uuids 목록을 유지하는 내 프로그램에 백그라운드 스레드를 수동으로 생성 할 수 있습니까?

+3

아직 배포 문제를 측정 했습니까? 그렇지 않다면 다른 것들에 대해 걱정하십시오. –

답변

6

정확하게 uuid 모듈이 예상 한 요청을 처리하는 데 너무 느리다는 것이 확실합니까? UUID 생성이 응용 프로그램의 병목 현상을 설명하면 매우 놀랍습니다.

단순히 응용 프로그램을 작성하여 uuid 모듈을 사용하고이 모듈이 실제로 느려지는 경우 미리 생성 된 UUID 목록을 유지하는 방법을 조사해야합니다.

+2

+1! 전혀! 이 모든 질문은 "시기 상조 최적화"를 암시합니다. 한 세트에서 팝하는 UUID가 즉석에서 생성하는 것보다 100 배 빠르더라도 전체 프로그램의 2 % 만 차지하는 경우 이러한 종류의 복잡성을 추가하는 데는 거의 요점이 없습니다. 이 코드를 멀티 스레드하면 어떻게됩니까? 이제 UUID 생성 스레드와 여러 UUID 소비 스레드 간의 액세스를 동기화해야합니다. 이것은 흥미로운 아이디어이지만 프로그램을 실행하고 UUID 세대가 성능 제한 항목이라는 것을 알게 될 때까지 계속 추구하십시오. – PaulMcG

+0

+1. 무엇인가 잘못되었을 때 일어날 재앙을 상상해보십시오. 동일한 GUID를 두 번 부여했습니다. 지금 –

4

나는 UUID를 생성에 대한 UUID 모듈의 성능을 테스트 한 :

>>> import timeit 
>>> timer=timeit.Timer('uuid.uuid1()','import uuid') 
>>> timer.repeat(3, 10000) 
[0.84600019454956055, 0.8469998836517334, 0.84400010108947754] 

당신이 얼마나 필요합니까? 초당 10000으로 충분하지 않습니까?

+1

>>> 타이머 = timeit.Timer 시도 ('uuids.pop()', '수입의 UUID]의 UUID = STR (uuid.uuid1()) xrange (10000)에 대한 _]) 100 배 이상 빠르다는 것을 알게 될 것입니다. – rjuiaa1

+0

@ rjuiaa, 나는'set'에서 터져 나오는 것이'list'에서 터지는 것보다 빠르다는 것을 알아 냈습니다. 내 대답에'set'을 사용했기 때문입니다. –

+0

나는리스트가리스트보다 빠르다는 것에 놀랍니다. 창조 측면은 어떨까요? 세트는 먼저 고유성을 보장해야합니다.이 경우 모든 종류의 UUID가 고유 할 것이라고 확신 할 수 있으므로이 경우 낭비입니다.기본 목록 데이터 저장소가 원인입니까? 아마도 deque는리스트를 사용하여 불필요한 유일성 검사 페널티를 발생시키지 않으면 서 목록 저장 문제를 해결할 수 있습니다. – PaulMcG

0

uuid 풀 풀을 유지할 스레드가 있다고 가정 해 보겠습니다.

여기에 당신은 또한 당신의 버스트를 생성 할 수 있습니다 빠른 스레드가 아닌 UUID의를 사용하여 풀을 비우는 경우를 처리해야 할 것입니다 매우 간단한 버전

import uuid,threading,time 

class UUID_Pool(threading.Thread): 
    pool_size=10000 
    def __init__(self): 
     super(UUID_Pool,self).__init__() 
     self.daemon=True 
     self.uuid_pool=set(uuid.uuid1() for x in range(self.pool_size)) 

    def run(self): 
     while True: 
      while len(self.uuid_pool) < self.pool_size: 
       self.uuid_pool.add(uuid.uuid1()) 
      time.sleep(0.01)    # top up the pool 100 times/sec 

uuid_pool = UUID_Pool() 
uuid_pool.start() 
get_uuid = uuid_pool.uuid_pool.pop  # make a local binding 
uuid=get_uuid()       # ~60x faster than uuid.uuid1() on my computer 

입니다.

+1

스레드를 통해 풀에 대한 액세스를 동기화 할 필요가 없습니까? 아니면'add'와'pop' 보장 된 threadsafe입니까? – PaulMcG

+0

또한 while while 루프는 매번 재 계산되는 불변량을 포함합니다. 모든 속성 액세스는이 알고리즘에서 루프마다 변경되지 않는 조회를 발생시킵니다. 루프를 시작하기 전에'self.uuid_pool','self.uuid_pool.add'와'uuid.uuid1'을 위해 지역 변수를 할당하십시오 - 심지어 지역에'len'을 할당하는 것이 더 빨리 실행되어 지역 vs 전역에 접근합니다. 이것이 미세 최적화입니까? 당연하지. 그러나 UUID 생성이 비용이 많이들 것이라는 생각이들 때, 왜 이러한 쉬운 최적화 단계를 생략합니까? – PaulMcG

+0

@Paul McGuire, 예'add'와'pop'은 threadsafe입니다. 최적화해야 할 부분은 uuids에 액세스하는 것이며, 버스트 사이에 풀을 채울 충분한 시간이 있다고 가정합니다. 'get_uid = uuid_pool.uuid_pool.pop'와 같은 로컬을 갖는 것이 좋은 생각 일 수 있습니다. –

관련 문제