2012-01-09 3 views
7

필자는 mechanize와 threading을 사용하여 웹 사이트에 연결하고 작업하는 데 사용하는 약 50 개의 클래스를 썼다. 그것들은 모두 동시에 작동하지만 서로 의존하지는 않습니다. 그래서 1 클래스 - 1 웹 사이트 - 1 스레드를 의미합니다. 특히 많은 코드가 각 클래스에서 반복되기 때문에 (코드를 관리하기위한) 특히 우아한 솔루션은 아닙니다. 그러나 일부 사이트에서는 메소드 중간에서 검색된 데이터의 추가 처리가 필요할 수 있으므로 클래스를 하나의 클래스로 만들 정도로는 충분하지 않습니다. - '로그인'과 같이 - 다른 사람들이 필요하지 않을 수도 있음). 제가 말했듯이, 그것은 우아하지 않습니다 - 그러나 그것은 효과적입니다. 말할 필요도없이 모든 권장 사항을 환영합니다. 각 웹 사이트 접근 방식에 대해 1 클래스를 사용하지 않고이 방법을 쓰는 것이 좋습니다. 각 클래스의 추가 기능 또는 전체 코드 관리를 추가하는 것은 어려운 작업입니다.스레드 된 파이썬 코드의 메모리 사용을 줄이는 방법은 무엇입니까?

그러나 각 스레드는 약 8MB의 메모리를 사용하므로 실행중인 스레드가 50 개인 경우 약 400MB의 사용률을 볼 수 있습니다. 내 시스템에서 실행 중이라면 문제가 없지만 1GB 메모리가있는 VPS에서 실행되므로 문제가되기 시작합니다. 메모리 사용량을 줄이는 방법을 알려주거나 여러 사이트를 동시에 사용하는 다른 방법이 있습니까?

이 빠른 테스트 파이썬 프로그램을 사용하여 메모리를 사용하는 응용 프로그램의 변수 또는 다른 데이터에 저장된 데이터인지 테스트합니다. 다음 코드에서 볼 수 있듯이 sleep() 함수 만 처리하지만 각 스레드는 8MB의 메모리를 사용합니다. 나는이 프로그램을 실행할 때

from thread import start_new_thread 
from time import sleep 

def sleeper(): 
    try: 
     while 1: 
      sleep(10000) 
    except: 
     if running: raise 

def test(): 
    global running 
    n = 0 
    running = True 
    try: 
     while 1: 
      start_new_thread(sleeper,()) 
      n += 1 
      if not (n % 50): 
       print n 
    except Exception, e: 
     running = False 
     print 'Exception raised:', e 
    print 'Biggest number of threads:', n 

if __name__ == '__main__': 
    test() 

, 출력은 다음과 같습니다

   total  used  free  shared buffers  cached 
Mem:   1536  1533   2   0   0   0 
-/+ buffers/cache:  1533   2 
Swap:   0   0   0 

실제를 :

50 
100 
150 
Exception raised: can't start new thread 
Biggest number of threads: 188 

그리고 running = False 라인을 제거하여

, 나는 다음 쉘에서 free -m 명령을 사용하여 사용 가능한 메모리를 측정 할 수 있습니다 계산 이유는 스레드 당 약 8MB를 차지하는 이유입니다. 위와 같은 테스트 응용 프로그램을 사용하기 전과 사용 된 메모리의 차이를 나누어 나누면 간단합니다. g를 시작할 수있는 최대 스레드로 나눈 값입니다.

top을 보면 파이썬 프로세스가 메모리의 약 0.6 %만을 사용하기 때문에 메모리를 할당했을 것입니다.

+0

무엇이 메모리를 차지합니까? 나는 당신이 그 사이트로부터 추출한 데이터라는 것을 추측하려고 노력할 것입니다. 그렇다면 실행중인 스레드의 수를 줄이거 나 할 수 없을만큼 많지는 않습니다. –

+0

정확히 어떻게 메모리 사용량을 측정합니까? 나는 그 8MB가 실제로 각 단일 스레드에 할당되지 않는다고 생각한다. 그 8MB의 큰 부분은 스레드 (그냥 추측 ..) 사이에 공유 될 수 있습니다? – Frunsi

+0

Demian and frunsi, 나는 내 질문을 모두 수정하여 귀하의 질문에 답변했습니다. 감사! – Gargauth

답변

0

저는 파이썬에 대한 전문가가 아니지만, 활성 스레드의 총 수를 제어하는 ​​몇 가지 스레드 풀을 가질 수 있으며, 이전 스레드에서 완료되면 스레드에 '요청'을 전달할 수 있습니다. 요청은 전체 스레드 객체 일 필요는 없으며 요청이 무엇이든 완료하기에 충분한 데이터입니다.

웹 사이트를 핑하는 N 스레드가있는 스레드 풀 A를 갖도록 구조화 할 수도 있습니다. 데이터를 검색하면 Y 스레드가 데이터를 처리하여 스레드 풀 B에 데이터를 전달합니다.

2

"요청 당 하나의 스레드"를 사용하면 많은 유스 케이스에서 쉽게 사용할 수 있습니다. 그러나 많은 리소스가 필요합니다 (경험 한대로).

더 나은 방법은 비동기식 방법을 사용하는 것이지만 불행히도 훨씬 더 복잡합니다.이 방향으로

일부 힌트 :

+0

감사합니다. 많이 감사합니다. 전에 Twisted에 대해 읽었지만, 슬프게도 그것에 대해 많이 알지 못합니다. 그리고 그 모습으로 기계화를 사용할 수 없었습니다. asyncore로 기계화 작업을 할 수 있는지 살펴 보겠습니다. – Gargauth

+0

결국 "완벽한"솔루션은 CPU 코어 당 하나의 스레드 (작업 처리를 위해 활용)와 비동기 IO를 가진 스레드 풀을 혼합 한 것입니다. 실용적인 솔루션은 실제 응용 프로그램 코드에 따라 다릅니다. 어쩌면,'select'를 기반으로 한 간단한 해결책조차도 당신을 위해서 할 것입니다. – Frunsi

+1

이것은 다음을 의미합니다. 쓰레드 : 요청들을 보내고 적절한 소켓에서 루프를 선택하고 들어오는 데이터를 하나씩 처리하는 등등. 어쨌든 OS는 소켓 IO에 신경을 쓴다. 가능한 가장 효율적인 방법으로 OS와 인터페이스하는 것이다. – Frunsi

1

솔루션은 다음과 같은 코드를 대체하는 것입니다 :

  • 비동기 접근을 시도 파이썬 2.X에 futures 설치 .
    2) 어떤 일이 생길 때까지 기다리십시오.
    3) 다른 작업을하십시오. 같은 코드로

    :

    1) 뭔가를 수행합니다.
    2) 어떤 일이 생기면 다른 일이 이루어 지도록 배치하십시오.
    3) 완료. 다른 곳

    , 당신은 이렇게 몇 스레드를 가지고 :

    1) 일이 아무것도 기다립니다.
    2) 발생한 일을 처리하십시오.
    3) 1 단계로 이동하십시오.

    50 가지가 발생하기를 기다리는 경우 50 가지 스레드가 발생하여 50 가지가 발생하기를 기다리고 있습니다. 두 번째 경우에는 기다려야 할 하나의 스레드가 있습니다.이 스레드 중 50 개가 완료되어야합니다.

    따라서 한 가지 일이 생길 때까지 기다리지 말고 스레드를 사용하지 마십시오. 대신, 그 일이 발생하면 다른 스레드가 다음에 수행해야 할 작업을 수행하도록 정렬하십시오.

  • 관련 문제