2010-12-07 11 views
9

मैं यह मापने के लिए एक आवेदन लिख रहा हूं कि मैं सी # का उपयोग करके वेब पेज कितनी तेजी से डाउनलोड कर सकता हूं। मैं अद्वितीय डोमेन नामों की एक सूची प्रदान करता हूं, फिर मैं थ्रेड की एक्स संख्या उत्पन्न करता हूं और डोमेन की सूची का उपभोग होने तक HTTPWebRequests निष्पादित करता हूं। समस्या यह है कि इससे कोई फर्क नहीं पड़ता कि मैं कितने धागे का उपयोग करता हूं, मुझे प्रति सेकंड लगभग 3 पृष्ठ मिलते हैं।HttpWebRequest पर Concurrency सीमा

मैंने पाया कि System.Net.ServicePointManager.DefaultConnectionLimit 2 है, लेकिन मैं इस धारणा के तहत था कि यह प्रति डोमेन कनेक्शन की संख्या से संबंधित है। चूंकि सूची में प्रत्येक डोमेन अद्वितीय है, यह कोई मुद्दा नहीं होना चाहिए।

तब मुझे पता चला कि GetResponse() विधि WebResponse बंद होने तक अन्य सभी प्रक्रियाओं से पहुंच को अवरुद्ध करती है: http://www.codeproject.com/KB/IP/Crawler.aspx#WebRequest, मुझे इस दावे को वापस करने के लिए वेब पर कोई अन्य जानकारी नहीं मिली है, हालांकि मैंने एक HTTP अनुरोध लागू किया है सॉकेट, और मैंने एक महत्वपूर्ण गति (4x से 6x) देखा।

तो मेरे प्रश्न: क्या कोई जानता है कि HttpWebRequest ऑब्जेक्ट्स कैसे काम करता है ?, क्या ऊपर वर्णित किए गए अलावा कोई कामकाज है ?, या सी # कहीं भी लिखे गए उच्च गति वाले वेब क्रॉलर के कोई उदाहरण हैं?

+0

आप प्रति डोमेन कनेक्शन सीमा को कॉन्फ़िगर कर सकते हैं, लेकिन डिफ़ॉल्ट रूप से कनेक्शन सीमा वैश्विक है। https://msdn.microsoft.com/en-us/library/fb6y0fyc.aspx – Todd

उत्तर

8

क्या आपने BeginGetResponse() जैसे async विधियों का उपयोग करने का प्रयास किया है?

यदि आप .NET 4.0 का उपयोग कर रहे हैं तो आप इस कोड को आजमा सकते हैं। अनिवार्य रूप से मैं एक विशिष्ट साइट पर 1000 अनुरोध करने के लिए कार्यों का उपयोग (मैं इस का उपयोग मेरी देव मशीन पर अनुप्रयोग के लोड परीक्षण करने के लिए और मैं इस तरह के रूप कोई सीमा नहीं देख के बाद से मेरे ऐप तेजी से उत्तराधिकार में इन अनुरोधों को देख रही है)

public partial class Form1 : Form 
    { 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     for (int i = 0; i < 1000; i++) 
     { 
     var webRequest = WebRequest.Create(textBox1.Text); 
     webRequest.GetReponseAsync().ContinueWith(t => 
     { 
      if (t.Exception == null) 
      { 
      using (var sr = new StreamReader(t.Result.GetResponseStream())) 
      { 
       string str = sr.ReadToEnd(); 
      } 
      } 
      else 
      System.Diagnostics.Debug.WriteLine(t.Exception.InnerException.Message); 
     }); 
     } 
    } 
    } 

    public static class WebRequestExtensions 
    { 
    public static Task<WebResponse> GetReponseAsync(this WebRequest request) 
    { 
     return Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null); 
    } 
    } 

चूंकि वर्कलोड यहां I/O बाध्य है, नौकरी पाने के लिए धागे को स्पॉन्ग करने की आवश्यकता नहीं है और वास्तव में प्रदर्शन को नुकसान पहुंचा सकता है। वेब क्लाइंट क्लास पर Async विधियों का उपयोग I/O समापन बंदरगाहों का उपयोग करें और इसलिए अधिक प्रदर्शन करने वाला और कम संसाधन भूख लगी होगी।

3

आपको BeginGetResponse विधि का उपयोग करना चाहिए जो अवरुद्ध नहीं है और असीमित है।

आई/ओ बाध्य एसिंक्रोनि से निपटने के दौरान, सिर्फ इसलिए कि आप I/O काम करने के लिए थ्रेड उत्पन्न करते हैं, वह थ्रेड अभी भी हार्डवेयर (इस मामले में नेटवर्क कार्ड) का जवाब देने के लिए अवरुद्ध हो जाएगा। यदि आप BeginGetResponse में निर्मित का उपयोग करते हैं, तो वह थ्रेड बस इसे नेटवर्क कार्ड पर कतारबद्ध करेगा, और फिर अधिक काम करने के लिए उपलब्ध होगा। जब हार्डवेयर किया जाता है, तो यह आपको सूचित करेगा, जिस बिंदु पर आपका कॉलबैक बुलाया जाएगा।

1

मैं ध्यान दें कि BeginGetResponse विधि पूरी तरह से अतुल्यकालिक नहीं है चाहते हैं: DNS रिज़ॉल्यूशन, प्रॉक्सी का पता लगाने, और TCP सॉकेट (MSDN से)

BeginGetResponse विधि पूरा होने में कुछ तुल्यकालिक सेटअप कार्यों की आवश्यकता है (कनेक्शन, उदाहरण के लिए) इस विधि से पहले असंकालिक हो जाता है। नतीजतन, इस विधि को किसी उपयोगकर्ता इंटरफ़ेस (UI) थ्रेड पर कभी नहीं कहा जाना चाहिए क्योंकि इसमें कुछ समय लग सकता है, आमतौर पर कई सेकंड।