2009-05-23 4 views
19

HttpWebResponse 클래스 +에서는 StreamReader 매우 느린 HttpWebResponse.GetResponse()와 Streamreader.ReadToEnd는(), 또한 StreamReader.Read를 사용하여 시도하여() 내 HTML 문자열을 작성하는 루프.내가 (단지 몇 백 개 사이트) C#에서 제한된 웹 크롤러를 구현하기 위해 노력하고있어

약 5-10K 페이지 만 다운로드 중입니다.

모두 매우 느립니다! 예를 들어 평균 GetResponse() 시간은 약 0.5 초이며 평균 StreamREader.ReadToEnd() 시간은 약 5 초입니다!

모든 사이트는 내 위치와 매우 흡사하며 빠른 서버를 사용해야하므로 매우 빠릅니다. (익스플로러에서 D/L을 거의 사용하지 않습니다.) 프록시를 사용하고 있지 않습니다.

내 크롤러는 동일한 사이트에서 동시에 약 20 개의 스레드를 읽습니다. 이것이 문제의 원인이 될 수 있습니까?

어떻게 StreamReader.ReadToEnd 번을 줄일 수 있습니까?

답변

8

WebClient의 DownloadString은 HttpWebRequest의 간단한 래퍼입니다. 일시적으로 사용하고 속도가 향상되는지 볼 수 있습니까? 일이 훨씬 빨라지면 코드를 공유하여 문제가 무엇인지 살펴볼 수 있습니까?

편집 :

그것은 HttpWebRequest를 보인다는 IE의 '최대 동시 연결'설정을 관찰, 같은 도메인에 이러한 URL은? 도움이되는지 확인하기 위해 연결 제한을 늘릴 수 있습니까? 나는이 문제에 대한 this article 발견 : 기본적으로

을, 당신은 더 많은 에 비해 2 ~ 3 비동기 HttpWebRequest를 (운영 체제에 을 따라 다름) 수행 할 수 없습니다. 위해서는이 (가장 쉬운 방법, IMHO)이 응용 프로그램의 설정 파일에 섹션이 추가 을 잊지 마세요 오버라이드 (override) :

<system.net> 
    <connectionManagement> 
    <add address="*" maxconnection="65000" /> 
    </connectionManagement> 
</system.net> 
+0

웹 클라이언트를 사용하여 시도, 동일한 결과 (평균 시간이 변경되지 않은 경우). 평균 1.5KBPS 연결에 180KBPS의 평균 d/l 속도가 있음을 언급해야합니다. 저는 StreamReader.Read를 동시에 호출하는 20 개의 스레드가 그와 관련이 있다고 생각 했습니까? 아니면 이건 부적절한가요? – Roey

+0

내 경험에 비추어 볼 때, 3-4 스레드로 대역폭을 포화시킬 수있는 연결이 필요합니다. ping을 수행하는 웹 사이트가 실제로 느리고 I/O를 기다리는 스레드가 많지 않으면 더 이상 실행할 필요가 없습니다. – kgriffs

+1

와우 !!! 비동기 HttpWebRequest를 사용하여 클라이언트 당 약 300 개의 스레드로 테스트 서버를로드하고 각 스레드는 "순차적으로"다운로드했습니다. maxconnection 설정을 변경하면 각 스레드가 데이터를 10 배 빠르게 다운로드 할 수 있습니다. –

15
의 HttpWebRequest는 proxy settings을 감지하는 동안 복용 할 수있다

. 응용 프로그램 설정이 추가보십시오 :

<system.net> 
    <defaultProxy enabled="false"> 
    <proxy/> 
    <bypasslist/> 
    <module/> 
    </defaultProxy> 
</system.net> 
당신은 또한 당신이 기본 운영 체제의 소켓에 호출 수 줄이기 위해 읽는 버퍼링에서 약간의 성능 향상을 볼 수 있습니다

:

using (BufferedStream buffer = new BufferedStream(stream)) 
{ 
    using (StreamReader reader = new StreamReader(buffer)) 
    { 
    pageContent = reader.ReadToEnd(); 
    } 
} 
+0

고마워요! 그것은 초 단위에서 수초에 이르는 속도를 완전히 가속화했습니다! –

+0

C++의 동일한 코드는 무엇입니까? 사용 (...) C++에서 작동하지 않습니다 – Edge

1

당신이 있으 ServicePointManager.maxConnections를 사용해 보셨습니까? 나는 보통 이것과 비슷한 것을 200으로 설정했다.

1

같은 문제가 있지만 최악입니다. 응답 = (HttpWebResponse) webRequest.GetResponse(); 내 코드에서 약 10 초 전에 더 많은 코드를 실행하기 전에 지연이 다운로드 내 연결을 포화.

커트의 대답 defaultProxy는

이 문제를 해결 = "false"를 활성화.지금은 응답이 거의 즉시이며 내 연결 최대 속도로 모든 HTTP 파일을 다운로드 할 수 있습니다 :) 죄송합니다, 나쁜 영어에

1

응용 프로그램 구성 방법이 작동하지 않았지만 여전히 프록시 설정으로 인해 문제가 발견. 30 초까지 걸릴하는 데 사용 내 간단한 요청은 지금은

public string GetWebData() 
{ 
      string DestAddr = "http://mydestination.com"; 
      System.Net.WebClient myWebClient = new System.Net.WebClient(); 
      WebProxy myProxy = new WebProxy(); 
      myProxy.IsBypassed(new Uri(DestAddr)); 
      myWebClient.Proxy = myProxy; 
      return myWebClient.DownloadString(DestAddr); 
} 
4

1. 저도 같은 문제가 있었다 걸리지 만 내가 null로의 HttpWebRequest의 프록시 매개 변수를 앉아 때, 그것은 문제를 해결했다.

UriBuilder ub = new UriBuilder(url); 
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(ub.Uri); 
request.Proxy = null; 
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 
+0

위대한 솔루션! 나를 위해 일합니다. –

0

답장을 보내 주셔서 감사합니다. 올바른 방향으로 파고 들도록 도와 주셨습니다. 내 요구에 맞지 않는 (I이 솔루션은 웹 응용 프로그램이라고 이해되는) 응용 프로그램의 설정 파일을 변경하는 솔루션을 제안하지만 나는이 같은 성능 문제에 직면 한, 내 솔루션은 다음과 같습니다 :

HttpWebRequest webRequest; 

webRequest = (HttpWebRequest)System.Net.WebRequest.Create(fullUrl); 
webRequest.Method = WebRequestMethods.Http.Post; 

if (useDefaultProxy) 
{ 
    webRequest.Proxy = System.Net.WebRequest.DefaultWebProxy; 
    webRequest.Credentials = CredentialCache.DefaultCredentials; 
} 
else 
{ 
    System.Net.WebRequest.DefaultWebProxy = null; 
    webRequest.Proxy = System.Net.WebRequest.DefaultWebProxy; 
} 
0

왜 멀티 스레딩이이 문제를 해결하지 않았습니까? 멀티 쓰레딩은 네트워크 대기 시간을 최소화하고, 버퍼 내용을 시스템 메모리 (RAM)에 저장하므로 파일 시스템을 다루는 데 따른 IO 병목 현상이 발생하지 않습니다. 따라서 다운로드 및 구문 분석에 82 초가 걸리는 82 페이지는 15 초 (4x 프로세서를 가정 할 때)와 같아야합니다. 내가 뭔가 빠진다면 정정 해줘.

____ 다운로드 THREAD _____ *

다운로드 내용

양식 스트림

읽기 내용

_________________________ *

+0

OP에는 이미 "약 20"개의 쓰레드가 사용된다고 나와 있습니다. – Spooky