1

私は基本的に2つのサブ機能に分かれている機能を持っています。

html=RetriveHTML(int index);
returnColection = RegexProcess(html, index);

RetrieveHTML の並列化を最適化して、このプロセスをスピードアップする最善の方法は何ですか?

通常、これを最大 20000 のインデックスで呼び出します。最初のサブ機能はネットワークに依存し (webclient.downloadstring を使用して 1 つのサーバーから複数の URL HTML を取得)、2 番目のサブ機能は主に CPU です。

Parallel foreach と Tasks(continue with, continueall, fromasync) の世界で迷子になり、解決策にたどり着くのに苦労しています。最初に Parallel foreach を簡単に試してみましたが、そのパフォーマンス、つまりネットワーク I/O が連続する呼び出しで低下することがわかりました (最初のループは速く、他のループは遅くなります)。解決策は、html オブジェクトが多くて大きいため、処理されるときにそれらを解放します。私は.net 4.0を使用しています...

4

1 に答える 1

0

こんにちは、以下のコードを試すことができます

private Regex _regex= new Regex("net");

        private void ProcessInParallell()
        {
           Uri[] resourceUri = new Uri[]{new Uri("http://www.microsoft.com"),new Uri( "http://www.google.com"),new Uri( "http://www.amazon.com") };


            //1. Stage 1: Download HTML

            //Use the blocking collection for concurrent tasks
            BlockingCollection<string> htmlDataList = new BlockingCollection<string>();

            Parallel.For(0, resourceUri.Length , index =>
                {   var html = RetrieveHTML(resourceUri[index]);

                    htmlDataList.TryAdd(html);

                    //If we reach to the last index, signal the completion
                    if (index == (resourceUri.Length - 1))
                    {   
                        htmlDataList.CompleteAdding();
                    }

                });


            //2. Get matches

            //This concurrent bags will be used to store the result of the matching stage
            ConcurrentBag<string> matchedHtml = new ConcurrentBag<string>();

            IList<Task> processingTasks  = new List<Task>();

            //Enumerate through each downloaded HTML document
            foreach (var html  in htmlDataList.GetConsumingEnumerable())
            {
                //Create a new task to match the downloaded HTML
              var task=   Task.Factory.StartNew((data) =>
                    {
                        var downloadedHtml = data as string;
                        if(downloadedHtml ==null)
                            return;

                        if (_regex.IsMatch(downloadedHtml))
                        {

                            matchedHtml.Add(downloadedHtml);
                        }

                    }, 
                     html  
                    );

                //Add the task to the waiting list
                processingTasks.Add(task);

            }

            //wait for the all tasks to complete
            Task.WaitAll(processingTasks.ToArray());



            foreach (var html in matchedHtml)
            {
                //Do something with the matched result    

            }




        }

        private string  RetrieveHTML(Uri uri)
        {
           using (WebClient webClient = new WebClient())
           {
               //set this to null if there is no proxy
               webClient.Proxy = null;

               byte[] data =webClient.DownloadData(uri);

               return Encoding.UTF8.GetString(data);
           }
        }
于 2013-01-23T00:29:13.443 に答える