2012-12-01 2 views
1

나는 pickle로 3 가지 프로토콜을 테스트한다. 내 테스트에서 0, 1, 2왜 pickle.HIGHEST_PROTOCOL로 덤프하고로드하는 것이 더 오래 걸립니까?

나는 버려진 약 560,000 int 하나에 대한 270000의 dict (int, int) 쌍과 하나 set로드. 다음

내 테스트 코드 (안전하게이 나는 데이터베이스에서 데이터 가져 오기 위해 사용하는 기능을 가져 건너 뛸 수 있습니다) :

Protocol: 0 
Time in dump: 31.3491470814 
Time in load: 29.8991980553 

Protocol: 1 
Time in dump: 32.3191611767 
Time in load: 20.6666529179 

Protocol: 2 
Time in dump: 94.2163629532 
Time in load: 42.7647490501 
:

protocol = 0 # Tested 0, 1, and 2 
print 'Protocol:', protocol 
t0 = time.time() 
sku2spu_dict = fetch_sku2spu_dict() 
pid_set = fetch_valid_pids() 
t1 = time.time() 
print 'Time in sql:', t1 - t0 
pickle.dump(sku2spu_dict, open('sku.pcike_dict', 'w'), protocol) 
pickle.dump(pid_set, open('pid.picke_set', 'w'), protocol) 
t2 = time.time() 
print 'Time in dump:', t2 - t1 
sku2spu_dict = pickle.load(open('sku.pcike_dict', 'r')) 
pid_set = pickle.load(open('pid.picke_set', 'r')) 
t3 = time.time() 
print 'Time in load:', t3 - t2 

그리고 다음은 각 하나에 의해 소요되는 시간입니다

놀랍게도 프로토콜 2는 0과 1보다 훨씬 나쁩니다.

그러나 덤프 된 파일 크기는 프로토콜 2의 약 절반 인 프로토콜에서 가장 작습니다 0 문서에서

1. 그것은 말한다 :

프로토콜 버전 2는 파이썬 2.3에 도입되었다. 새로운 스타일의 클래스를 훨씬 더 효율적으로 산세 처리합니다.

그리고 new-style classes의 정의에 대한

, 그것은 말한다 :

개체에서 상속 모든 클래스. 여기에는 list와 dict와 같은 모든 내장 유형이 포함됩니다.

그래서 프로토콜 2가 객체를 덤프 및로드하는 데 더 빠를 것으로 예상했습니다.

누구나 알 수 있습니까?

UPDATE : cPicklepickle으로 교체 후 해결

문제.

이제 loaddump은 프로토콜 2로 5 초 및 3 초 걸리는 반면 프로토콜 0과 1은 10 초 이상 걸립니다.

+1

관심 분야에서 타이밍에 대한 방법은 무엇입니까? 질문이 실행 속도와 관련이있는 경우 일반적으로 누군가가 테스트를 직접 실행하는 데 필요한 모든 것을 제공하는 것이 가장 좋습니다. –

+0

@Lattyware 업데이트 된 게시물을 참조하십시오. –

+1

그런 종류의 테스트는 그다지 정확하지 않고 대신 [timeit' 모듈 (http://docs.python.org/2/library/timeit.html)을 살펴보십시오. –

답변

2

"new-style classes"에 대한 문서에서는 사용자 정의 된 새 스타일 클래스를 참조합니다.

>>> dumped = cPickle.dumps(MyObject(100), 0) 
>>> timeit.timeit('cPickle.loads(dumped)', 'from __main__ import cPickle, dumped') 
4.6161839962005615 
>>> dumped = cPickle.dumps(MyObject(100), 1) 
>>> timeit.timeit('cPickle.loads(dumped)', 'from __main__ import cPickle, dumped') 
4.351701021194458 
>>> dumped = cPickle.dumps(MyObject(100), 2) 
>>> timeit.timeit('cPickle.loads(dumped)', 'from __main__ import cPickle, dumped') 
2.3936450481414795 

에서 : 2 배 속도 업에

>>> import cPickle 
>>> import timeit 
>>> class MyObject(object): 
...  def __init__(self, val): 
...    self.val = val 
...  def method(self): 
...    print self.val 
... 
>>> timeit.timeit('cPickle.dumps(MyObject(100), 0)', 'from __main__ import cPickle, MyObject') 
17.654622077941895 
>>> timeit.timeit('cPickle.dumps(MyObject(100), 1)', 'from __main__ import cPickle, MyObject') 
14.536609172821045 
>>> timeit.timeit('cPickle.dumps(MyObject(100), 2)', 'from __main__ import cPickle, MyObject') 
8.885567903518677 

또한로드 결과 : 당신이 그들과 함께 간단한 벤치 마크를 할 경우 그리고 당신은 그 프로토콜이 그들을 투기의 프로토콜이 0보다 두 배 빠른 볼 수 있습니다 특별한 경우 그것은 반대 일지 모르지만 fetch_sku2spu_dict 등을 정의하는 코드가 없으면 아무 것도 말할 수 없습니다. 반환되는 값은 dict이지만 그 경우 프로토콜 2는 약 6 배 빠릅니다 :

>>> mydict = dict(zip(range(100), range(100))) 
>>> timeit.timeit('cPickle.dumps(mydict, 0)', 'from __main__ import cPickle, mydict') 
46.335021018981934 
>>> timeit.timeit('cPickle.dumps(mydict, 1)', 'from __main__ import cPickle, mydict') 
7.913743019104004 
>>> timeit.timeit('cPickle.dumps(mydict, 2)', 'from __main__ import cPickle, mydict') 
7.798863172531128 

약 2입니다.5 배 빠른 로딩에 :

>>> mydict = dict(zip(range(100), range(100))) 
>>> timeit.timeit('pickle.dumps(mydict,0)', 'from __main__ import pickle, mydict', number=10000) 
2.9552500247955322 
>>> timeit.timeit('pickle.dumps(mydict,1)', 'from __main__ import pickle, mydict', number=10000) 
3.831756830215454 
>>> timeit.timeit('pickle.dumps(mydict,2)', 'from __main__ import pickle, mydict', number=10000) 
3.842888116836548 

그래서이 내장 된 투기 목적처럼 보인다 : 모듈의 파이썬 버전을 사용하는 경우

>>> dumped = cPickle.dumps(mydict, 0) 
>>> timeit.timeit('cPickle.loads(dumped)', 'from __main__ import cPickle, dumped') 
32.81050395965576 
>>> dumped = cPickle.dumps(mydict, 1) 
>>> timeit.timeit('cPickle.loads(dumped)', 'from __main__ import cPickle, dumped') 
13.997781038284302 
>>> dumped = cPickle.dumps(mydict, 2) 
>>> timeit.timeit('cPickle.loads(dumped)', 'from __main__ import cPickle, dumped') 
14.006750106811523 

다른 측면에서, 나는 것을 발견 프로토콜 1과 2는 파이썬 버전에서 프로토콜 0을 사용하는 것보다 느립니다. 객체를로드 할 때 프로토콜 0 다시 세의 느린입니다 :

>>> dumped = pickle.dumps(mydict, 0) 
>>> timeit.timeit('pickle.loads(dumped)', 'from __main__ import pickle, dumped', number=10000) 
2.988792896270752 
>>> dumped = pickle.dumps(mydict, 1) 
>>> timeit.timeit('pickle.loads(dumped)', 'from __main__ import pickle, dumped', number=10000) 
1.2793281078338623 
>>> dumped = pickle.dumps(mydict, 2) 
>>> timeit.timeit('pickle.loads(dumped)', 'from __main__ import pickle, dumped', number=10000) 
1.5425071716308594 

당신은 위의 미니 벤치 마크에서 볼 수 피클에 걸리는 시간은 당신이 개체의 유형에서, 여러 가지 요인에 따라 달라 사용하는 피클 모듈의 버전을 피클 링합니다. 더 자세한 정보가 없으면 우리의 경우 프로토콜 2가 왜 그렇게 느린지를 설명 할 수 없을 것입니다.

관련 문제