2012-06-14 2 views
0

&이 많은 페이지를 한 번에로드하는 클라이언트를 작성 중이므로 &이 서버로 데이터를 보냅니다. 난 그냥 한 번에 한 페이지 프로세서를 실행하면 상황이 합리적으로 잘 이동합니다파이썬 : urlopen 및 스레딩 불필요하게 느린? 더 빠른 방법이 있습니까?

********** Round-trip (with 0 sends/0 loads) for (+0/.0/-0) was total 1.98s (1.60s load html, 0.24s parse, 0.00s on queue, 0.14s to process) ********** 
********** Round-trip (with 0 sends/0 loads) for (+0/.0/-0) was total 1.87s (1.59s load html, 0.25s parse, 0.00s on queue, 0.03s to process) ********** 
********** Round-trip (with 0 sends/0 loads) for (+0/.0/-0) was total 2.79s (1.78s load html, 0.28s parse, 0.00s on queue, 0.72s to process) ********** 
********** Round-trip (with 0 sends/1 loads) for (+0/.0/-0) was total 2.18s (1.70s load html, 0.34s parse, 0.00s on queue, 0.15s to process) ********** 
********** Round-trip (with 0 sends/1 loads) for (+0/.0/-0) was total 1.91s (1.47s load html, 0.21s parse, 0.00s on queue, 0.23s to process) ********** 
********** Round-trip (with 0 sends/1 loads) for (+0/.0/-0) was total 1.84s (1.59s load html, 0.22s parse, 0.00s on queue, 0.03s to process) ********** 
********** Round-trip (with 0 sends/0 loads) for (+0/.0/-0) was total 1.90s (1.67s load html, 0.21s parse, 0.00s on queue, 0.02s to process) ********** 

그러나 ~ 20 번에 실행 (자체 스레드에서 각)는 HTTP 트래픽은 현저하게 느린 가져옵니다

********** Round-trip (with 2 sends/7 loads) for (+0/.0/-0) was total 23.37s (16.39s load html, 0.30s parse, 0.00s on queue, 6.67s to process) ********** 
********** Round-trip (with 2 sends/5 loads) for (+0/.0/-0) was total 20.99s (14.00s load html, 1.99s parse, 0.00s on queue, 5.00s to process) ********** 
********** Round-trip (with 4 sends/4 loads) for (+0/.0/-0) was total 17.89s (9.17s load html, 0.30s parse, 0.12s on queue, 8.31s to process) ********** 
********** Round-trip (with 3 sends/5 loads) for (+0/.0/-0) was total 26.22s (15.34s load html, 1.63s parse, 0.01s on queue, 9.24s to process) ********** 

load html 비트는 처리중인 웹 페이지의 HTML을 읽는 데 걸리는 시간입니다 (resp = self.mech.open(url)에서 resp.read(); resp.close()). to process 비트는이 클라이언트에서이를 처리하는 서버로 왕복하는 데 걸리는 시간입니다 (fp = urllib2.urlopen(...); fp.read(); fp.close()). X sends/Y loads 비트는 서버로의 동시 전송 수이며 서버로의 요청이 이루어질 때 실행중인 웹 페이지에서로드됩니다.

나는 to process 비트에 대해 가장 염려합니다. 서버에서 실제 처리는 0.2s 정도 걸립니다. 400 바이트 만 전송되므로 너무 많은 대역폭을 사용하지 않아도됩니다. 흥미로운 것은 5 개 스레드를 열고 반복적으로 바로 to process 비트를 수행합니다 (구문 분석이 모든 동시 전송/로딩 진행되는 동안) 내가 프로그램을 실행하면 현저하게 빠른 진행이다 :

1 took 0.04s 
1 took 1.41s in total 
0 took 0.03s 
0 took 1.43s in total 
4 took 0.33s 
2 took 0.49s 
2 took 0.08s 
2 took 0.01s 
2 took 1.74s in total 
3 took 0.62s 
4 took 0.40s 
3 took 0.31s 
4 took 0.33s 
3 took 0.05s 
3 took 2.18s in total 
4 took 0.07s 
4 took 2.22s in total 

to process 이 독립 실행 형 프로그램에서는 0.01s부터 0.50s까지 전체 작성 버전에서 6-10 초보다 훨씬 적게 걸리며 송신 스레드를 적게 사용하지 않습니다 (5를 사용하며 본격적인 버전은 제한적입니다). 5시에).

즉, 본격적인 버전이 실행되는 동안 각각의 400 바이트의 동일한 (+0/.0/-0) 요청을 보내는 별도의 버전을 실행하면 각 요청에 대해 0.31 초가 걸립니다. 그래서, 내가 쓰고있는 머신이 도청당하는 것과 같지 않다 ... 다른 쓰레드의 여러 동시로드가 빠른 속도로 느려지는 것 같다. (그리고 실제로 실행중인 다른 프로그램에서 빠르다. 동일한 컴퓨터)가 다른 스레드에서 보냅니다.

송신은 urllib2.urlopen으로 이루어지며 기계 판독 (마지막으로 urllib2.urlopen의 포크 사용)으로 읽는 중입니다.

적어도 같은 일을 보내고있을 때,이 미니 스탠드 얼론 버전처럼 빨리 실행되는 프로그램을 만들 수있는 방법이 있습니까? 나는 named pipe 나 어떤 것을 통해 보낼 것을 요구하는 다른 프로그램을 작성하려고 생각하고있다. 그래서 send는 다른 프로세스에서 수행되지만 어쨌든 어리석은 것처럼 보인다. 어떤 제안이라도 환영받을 것입니다.

여러 개의 동시 페이지로드를 더 빨리 수행하는 방법에 대한 제안 사항 (따라서 시간이 10-20 초가 아닌 1-3 초처럼 보임)을 환영합니다.


편집 : 추가 참고 : 나는 기계화의 쿠키 처리 기능에 의존하므로, 어떠한 대답은 이상적으로뿐만 아니라, 그 처리 할 수있는 방법을 제공 할 것 ...


편집 : 나는 한 페이지가 열리고 ~ 10-20 것들이 한 번에 대기열에 추가되는 다른 설정으로 동일한 설정을했습니다.버터를 통해 나이프처럼 가공됩니다. 참고

********** Round-trip (with 4 sends/0 loads) for (+0/.0/-0) was total 1.17s (1.14s wait, 0.04s to process) ********** 
********** Round-trip (with 4 sends/0 loads) for (+0/.0/-0) was total 1.19s (1.16s wait, 0.03s to process) ********** 
********** Round-trip (with 4 sends/0 loads) for (+0/.0/-0) was total 1.26s (0.80s wait, 0.46s to process) ********** 
********** Round-trip (with 4 sends/0 loads) for (+0/.0/-0) was total 1.35s (0.77s wait, 0.58s to process) ********** 
********** Round-trip (with 4 sends/0 loads) for (+2/.4/-0) was total 1.44s (0.24s wait, 1.20s to process) ********** 

가 (. 나는 정보가 전송되기 전에 큐에 앉아 시간입니다 wait 타이밍을 추가)을 to process가 최대한 빨리이다 : 여기를 왕창 추가 한의 꼬리 끝입니다 독립 실행 형 프로그램이었다. 문제는 꾸준히 웹 페이지를 구문 분석하는 &을 읽는 경우에만 나타납니다. (파싱 자체는 많은 CPU를 필요로합니다.)


편집이 : 그가 실행되면 일부 예비 테스트 난 그냥 각 웹 페이지로드에 대해 별도의 프로세스를 사용한다 나타냅니다 ... 업데이 트를 게시 할 예정입니다.

+0

모든 다른 스레드간에 공유 리소스가 있습니까? 락/뮤텍스의 획득과 해제로 인해 대기 시간이 길어지는 것일까? – JustinDanielson

+0

@JustinDanielson : 짧은 대답 : 아니오. 'to process' 시간은 응답이 닫힌 직후에 urllib2.urlopen 호출이 이루어지기 직전에 문자 그대로 걸리는 시간입니다. 이것은 엄격하게 I/O 소요 시간이며 차단이 필요 없습니다. 그것이 내가 최소화하고자하는 숫자입니다. 나는 내 대답에 약간의 정보를 추가했다. – Claudiu

답변

1

아마도 GIL (Global Interpreter Lock) 일 것입니다. 대신 멀티 프로세싱 모듈을 사용해 보셨습니까 (대부분 스레딩을위한 드롭 인 대체, IIRC)?

Python code performance decreases with threading

+0

다중 처리로 모든 문제가 해결되었습니다! 페이지로드 시간, 구문 분석 시간 및 서버 왕복 시간이 모두 10 배 감소했습니다. 칭찬 멀티 프로세싱하는 것입니다! (대안 : 와우, 파이썬 스레딩은 정말 짜증나!) – Claudiu

관련 문제