Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.73/15: Рейтинг темы: голосов - 15, средняя оценка - 4.73
4 / 4 / 1
Регистрация: 12.06.2011
Сообщений: 111
.NET 4.x

Как оптимизировать код, где используется много методов .Contains?

22.04.2013, 08:06. Показов 2977. Ответов 30
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Есть задача поиска всех url'ов на каком то сайте и найти в них битые/небитые. Задачу решил с использованием Selenium WebDriver. В его помощью я легко получаю все нужные мне ссылки. Но вот только после того, как страница сайта была загружена и из её кода были выдраны url'ы, мне нужно проверить, не обрабатывал ли я уже такую url'ку, нет ли её уже в каком нибудь списке. Для этого использую метод .Contains. Вот только использую аж 5 штук подряд) И получается ситуация, что страница уже загружена, а из-за моих проверок прога висит. Можно ли как то оптимизировать мой код:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
static void Main(string[] args)
        {
            IWebDriver driver = new ChromeDriver();
            //----------------------------------------------
            
            ArrayList brokenLinks = new ArrayList();
            ArrayList workingLinks = new ArrayList();
            ArrayList visitedLinks = new ArrayList();
            ArrayList externalLinksToVisit = new ArrayList();
            Stack<string> internalLinksToVisit = new Stack<string>();
            bool needToStop = false;
            string domainName = "http://isokor.pinstudio.ru/";
            string url = string.Empty;
            string startUrl = string.Empty; 
            HttpWebRequest webRequest = null;
            HttpWebResponse response = null;
 
            internalLinksToVisit.Push(domainName);
 
            while (needToStop == false)
            {
                startUrl = internalLinksToVisit.Pop();
                driver.Navigate().GoToUrl(startUrl);
                visitedLinks.Add(startUrl);
 
                try
                {
                    webRequest = (HttpWebRequest)WebRequest.Create(startUrl);
                    webRequest.AllowAutoRedirect = false;
                    webRequest.Timeout = 5000;
 
                    response = (HttpWebResponse)webRequest.GetResponse();
                    Console.WriteLine(startUrl + " - " + ((int)response.StatusCode).ToString());
 
                    if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Moved && response.StatusCode != HttpStatusCode.MovedPermanently)
                    {
                        brokenLinks.Add(startUrl);
                    }
                    else
                    {
                        workingLinks.Add(startUrl);
                    }
                }
                catch (NotSupportedException)
                {
                    Console.WriteLine(startUrl + " - " + "невозможно определить код ответа");
                }
                catch (WebException e)
                {
                    brokenLinks.Add(startUrl + " - " + ((int)((HttpWebResponse)e.Response).StatusCode).ToString());
                    Console.WriteLine(startUrl + " - " + ((int)((HttpWebResponse)e.Response).StatusCode).ToString());
                }
                finally
                {
                    response.Close();
                }
 
                foreach (IWebElement element in driver.FindElements(By.TagName("a")))
                {
                    url = element.GetAttribute("href");
 
                    if (url != null)
                    {
                        if (url.Contains("#"))
                        {
                            continue;
                        }
 
                        if (internalLinksToVisit.Contains(url) == false && externalLinksToVisit.Contains(url) == false && visitedLinks.Contains(url) == false)
                        {
                            if (url.Contains(domainName) == true)
                            {
                                internalLinksToVisit.Push(url);
                            }
                            else
                            {
                                externalLinksToVisit.Add(url);
                            }
                        }
                    }
                }
 
                if (internalLinksToVisit.Count == 0)
                {
                    needToStop = true;
                }
            }
            
            //----------------------------------------------
 
            driver.Quit();
            Console.ReadKey();
        }
    }
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
22.04.2013, 08:06
Ответы с готовыми решениями:

Код потребляет очень много памяти. Подскажите как оптимизировать?
Есть код на C++ (компилируется под GCC) - подсчёт коэффициентов осцилляторной системы методом Рунге-Кутта (метод в простейшем случае)....

Оптимизировать код парсинга страниц. Используется SimpleHtmlDom
Как оптимизировать подобное: $url2=('http://cайт1/'); $table2 = array(); $data2 = file_get_html($url2, false, $context); ...

Где научиться оптимизировать код?
Подскажите хорошие уроки, желательно на русском, по отладке ошибок ПХП, нахождение, исправление ошибок, ускорение работы сервера,...

30
Эксперт Python
 Аватар для dondublon
4652 / 2072 / 366
Регистрация: 17.03.2012
Сообщений: 10,182
Записей в блоге: 6
22.04.2013, 08:49
Используйте Dictionary с вашими url'ами в качестве ключей.
Там, правда, добавление медленнее.
0
4 / 4 / 1
Регистрация: 12.06.2011
Сообщений: 111
22.04.2013, 11:52  [ТС]
Цитата Сообщение от dondublon Посмотреть сообщение
Используйте Dictionary с вашими url'ами в качестве ключей.
Там, правда, добавление медленнее.
А чем мне это поможет? Насколько я знаю Dictionary - это штука, чтобы заменить значения переменных какими то человекопонятными словами. Не?
0
Эксперт Python
 Аватар для dondublon
4652 / 2072 / 366
Регистрация: 17.03.2012
Сообщений: 10,182
Записей в блоге: 6
22.04.2013, 12:07
Цитата Сообщение от Vlad10 Посмотреть сообщение
А чем мне это поможет? Насколько я знаю Dictionary - это штука, чтобы заменить значения переменных какими то человекопонятными словами. Не?
Dictionary - набор пар "ключ-значение", оптимизированный для поиска по ключу.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
22.04.2013, 14:13
Vlad10, замените просто Arraylist на HashSet<string> Все остальное оставьте как есть.

Добавлено через 1 минуту
И на будущее: откажитесь от ВСЕХ случаев использования ArrayList, как глючного тормознутого... Фигни...

Добавлено через 1 минуту
dondublon, словарь тут не при чем, достаточно сета
0
Эксперт Python
 Аватар для dondublon
4652 / 2072 / 366
Регистрация: 17.03.2012
Сообщений: 10,182
Записей в блоге: 6
22.04.2013, 14:20
Цитата Сообщение от Psilon Посмотреть сообщение
dondublon, словарь тут не при чем, достаточно сета
Внутри словаря все равно сет, просто про отдельный класс был не в курсе.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
22.04.2013, 14:31
dondublon, то да
0
4 / 4 / 1
Регистрация: 12.06.2011
Сообщений: 111
22.04.2013, 15:03  [ТС]
Цитата Сообщение от Psilon Посмотреть сообщение
Vlad10, замените просто Arraylist на HashSet<string> Все остальное оставьте как есть.
И это действительно так, время простоя на самой заполненной ссылками странице не больше секунды. Спасибо! Меня в принципе устраивает. Другое дело, в цикле есть кусок кода:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
                try
                {
                    webRequest = (HttpWebRequest)WebRequest.Create(startUrl);
                    webRequest.AllowAutoRedirect = false;
                    webRequest.Timeout = 5000;
 
                    response = (HttpWebResponse)webRequest.GetResponse();
                    Console.WriteLine(startUrl + " - " + ((int)response.StatusCode).ToString());
 
                    if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Moved && response.StatusCode != HttpStatusCode.MovedPermanently)
                    {
                        brokenLinks.Add(startUrl);
                    }
                    else
                    {
                        workingLinks.Add(startUrl);
                    }
                }
                catch (NotSupportedException)
                {
                    Console.WriteLine(startUrl + " - " + "невозможно определить код ответа");
                }
                catch (WebException e)
                {
                    brokenLinks.Add(startUrl + " - " + ((int)((HttpWebResponse)e.Response).StatusCode).ToString());
                    Console.WriteLine(startUrl + " - " + ((int)((HttpWebResponse)e.Response).StatusCode).ToString());
                }
                finally
                {
                    response.Close();
                }
Это чтобы узнать код ответа страницы. Он мне нужен, но он подтормаживает мой цикл где то на 0,2-0,5 секунды. Мне в принципе пофиг уже, даже с этим на каждую страницу уходит где то по секунде + прога будет запускаться по ночам на каком нибудь сервере, но всё же. Хотя тут наверное уже ничего не сделаешь.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
22.04.2013, 15:06
Vlad10, у вас есть возможность сначала создать массив ссылок, а потом в foreAch его обходить?
0
4 / 4 / 1
Регистрация: 12.06.2011
Сообщений: 111
22.04.2013, 15:12  [ТС]
Цитата Сообщение от Psilon Посмотреть сообщение
Vlad10, у вас есть возможность сначала создать массив ссылок, а потом в foreAch его обходить?
Да, так сначала и было. Я сначала делал ссылки, потом проверял код. Потом подумал, что быстрее будет сразу ссылку проверять. Думаете, если я верну обратно, то будет быстрее?
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
22.04.2013, 16:10
Vlad10, если будет форич, можно будет запустить все обработки параллельно, тогда время работы вряд ли будет дольше времени загрузки самой долгой страницы. Переделайте в foreach, я вам покажу
0
4 / 4 / 1
Регистрация: 12.06.2011
Сообщений: 111
22.04.2013, 17:42  [ТС]
Вот переделанный код
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
IWebDriver driver = new ChromeDriver();
            
            //----------------------------------------------
            //Сбор ссылок с сайта
 
            HashSet<string> brokenLinks = new HashSet<string>();
            HashSet<string> workingLinks = new HashSet<string>();
            HashSet<string> visitedLinks = new HashSet<string>();
            HashSet<string> externalLinksToVisit = new HashSet<string>();
            Stack<string> internalLinksToVisit = new Stack<string>();
            bool needToStop = false;
            string domainName = "http://isokor.pinstudio.ru/";
            string url = string.Empty;
            string startUrl = string.Empty; 
            HttpWebRequest webRequest = null;
            HttpWebResponse response = null;
 
            internalLinksToVisit.Push(domainName);
 
            while (needToStop == false)
            {
                startUrl = internalLinksToVisit.Pop();
                driver.Navigate().GoToUrl(startUrl);
                visitedLinks.Add(startUrl);
 
                foreach (IWebElement element in driver.FindElements(By.TagName("a")))
                {
                    url = element.GetAttribute("href");
 
                    if (url != null)
                    {
                        if (url.Contains("#"))
                        {
                            continue;
                        }
 
                        if (internalLinksToVisit.Contains(url) == false && externalLinksToVisit.Contains(url) == false && visitedLinks.Contains(url) == false)
                        {
                            if (url.Contains(domainName) == true)
                            {
                                internalLinksToVisit.Push(url);
                            }
                            else
                            {
                                externalLinksToVisit.Add(url);
                            }
                        }
                    }
                }
 
                if (internalLinksToVisit.Count == 0)
                {
                    needToStop = true;
                }
            }
 
            //----------------------------------------------
            //Получение кодов ответа
 
            foreach (string link in visitedLinks)
            {
                try
                {
                    webRequest = (HttpWebRequest)WebRequest.Create(link);
                    webRequest.AllowAutoRedirect = false;
                    webRequest.Timeout = 5000;
 
                    response = (HttpWebResponse)webRequest.GetResponse();
                    Console.WriteLine(link + " - " + ((int)response.StatusCode).ToString());
 
                    if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Moved && response.StatusCode != HttpStatusCode.MovedPermanently)
                    {
                        brokenLinks.Add(link);
                    }
                    else
                    {
                        workingLinks.Add(link);
                    }
                }
                catch (NotSupportedException)
                {
                    Console.WriteLine(link + " - " + "невозможно определить код ответа");
                }
                catch (WebException e)
                {
                    brokenLinks.Add(link + " - " + ((int)((HttpWebResponse)e.Response).StatusCode).ToString());
                    Console.WriteLine(link + " - " + ((int)((HttpWebResponse)e.Response).StatusCode).ToString());
                }
                finally
                {
                    response.Close();
                }
            }
            
            //----------------------------------------------
Теперь получение кода ответа в фориче.

P/S. У HashSet<string> нету метода .Sort(). Обидно =((((((((
0
28 / 28 / 6
Регистрация: 25.12.2008
Сообщений: 186
22.04.2013, 17:51
Цитата Сообщение от Vlad10 Посмотреть сообщение
P/S. У HashSet<string> нету метода .Sort(). Обидно =((((((((
Можно написать...
0
4 / 4 / 1
Регистрация: 12.06.2011
Сообщений: 111
22.04.2013, 17:54  [ТС]
Цитата Сообщение от Sinys Посмотреть сообщение
Можно написать...
Можно, но он будет корявый же. А стандартные методы уже максимально крутые.
0
28 / 28 / 6
Регистрация: 25.12.2008
Сообщений: 186
22.04.2013, 18:06
Цитата Сообщение от Vlad10 Посмотреть сообщение
ожно, но он будет корявый же. А стандартные методы уже максимально крутые.
по прежнему сортирует элементы... и не настолько оно было бы оптимизировано...
1
4 / 4 / 1
Регистрация: 12.06.2011
Сообщений: 111
22.04.2013, 18:08  [ТС]
Цитата Сообщение от Sinys Посмотреть сообщение
по прежнему сортирует элементы... и не настолько оно было бы оптимизировано...
Решил проблему так:
C#
1
2
List<string> ff = visitedLinks.ToList();
            ff.Sort();
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
22.04.2013, 19:28
Vlad10, Есть понятие SortedSet == HashSet + sort. Только не вижу смысла в сортировке в данной задаче. А приведение к листу теряет всю эффективность сетов.

я отрефакторил, как мог, ну и добавил параллельность:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
private static void Foo()
        {
            var driver = new ChromeDriver();
 
            //----------------------------------------------
            //Сбор ссылок с сайта
 
            var brokenLinks = new HashSet<string>();
            var workingLinks = new HashSet<string>();
            var visitedLinks = new HashSet<string>();
            var externalLinksToVisit = new HashSet<string>();
            var internalLinksToVisit = new Stack<string>();
            const string domainName = "http://isokor.pinstudio.ru/";
 
            internalLinksToVisit.Push(domainName);
 
            do
            {
                string startUrl = internalLinksToVisit.Pop();
                driver.Navigate().GoToUrl(startUrl);
                visitedLinks.Add(startUrl);
 
                foreach (IWebElement element in driver.FindElements(By.TagName("a")))
                {
                    string url = element.GetAttribute("href");
 
                    if (url != null)
                    {
                        if (url.Contains("#"))
                        {
                            continue;
                        }
 
                        if (
                            !(internalLinksToVisit.Contains(url) || externalLinksToVisit.Contains(url) ||
                              visitedLinks.Contains(url)))
                        {
                            if (url.Contains(domainName))
                            {
                                internalLinksToVisit.Push(url);
                            }
                            else
                            {
                                externalLinksToVisit.Add(url);
                            }
                        }
                    }
                }
            } while (internalLinksToVisit.Count != 0);
 
            //----------------------------------------------
            //Получение кодов ответа
 
 
            Parallel.ForEach(visitedLinks, link =>
                {
                    HttpWebResponse response = null;
                    try
                    {
                        var webRequest = (HttpWebRequest) WebRequest.Create(link);
                        webRequest.AllowAutoRedirect = false;
                        webRequest.Timeout = 5000;
 
                        response = (HttpWebResponse) webRequest.GetResponse();
                        Console.WriteLine(link + " - " + ((int) response.StatusCode).ToString());
 
                        if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.Moved &&
                            response.StatusCode != HttpStatusCode.MovedPermanently)
                        {
                            brokenLinks.Add(link);
                        }
                        else
                        {
                            workingLinks.Add(link);
                        }
                    }
                    catch (NotSupportedException)
                    {
                        Console.WriteLine(link + " - " + "невозможно определить код ответа");
                    }
                    catch (WebException e)
                    {
                        brokenLinks.Add(link + " - " + ((int) ((HttpWebResponse) e.Response).StatusCode).ToString());
                        Console.WriteLine(link + " - " +
                                          ((int) ((HttpWebResponse) e.Response).StatusCode).ToString());
                    }
                    finally
                    {
                        if (response != null) response.Close();
                    }
                });
        }
0
4 / 4 / 1
Регистрация: 12.06.2011
Сообщений: 111
22.04.2013, 19:54  [ТС]
Большое спасибо! Сейчас буду пробовать. Сортировка в данной задаче нужна, т.к. сбор ссылок - только самое начало огроменной проги. Разработчикам будет удобнее отсортированное читать.

Пока есть вопросы:
1. Почему во всех переменных написан var? Я знаю, что var сам определяет тип, так типа надёжнее?
2.
C#
1
2
3
if (
                            !(internalLinksToVisit.Contains(url) || externalLinksToVisit.Contains(url) ||
                              visitedLinks.Contains(url)))
Это работает как то быстрее или просто вам не понравилось 3 моих ==false?
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6102 / 4958 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
22.04.2013, 19:59
Vlad10,
1. Почему во всех переменных написан var? Я знаю, что var сам определяет тип, так типа надёжнее?
с var проще читать, справа и так написано, что это за переменная. int, char, string, double - можно писать и так, а вот для всяких классов, из записи
C#
1
var person = new Person();
и так понятно, что за person. А запись
C#
1
Person person = new Person();
только загромождает код
2. Это работает как то быстрее или просто вам не понравилось 3 моих ==false?
== false - не принято писать, да и быстрее конечно взять уже готовое значение, чем проводить лишнее сравнение, даже с константой.
0
4 / 4 / 1
Регистрация: 12.06.2011
Сообщений: 111
22.04.2013, 20:06  [ТС]
Сделал, теперь коды ответа вообще супер быстро получаю. А во сколько потоков это делается?
И ещё, я сейчас поставил получение кодов в бесконечный цикл, чтобы посмотреть не банит ли меня сервер. Так вот, после 2000 раз у меня уже 2 раз вылезает AggregateException. Если просто нажать на продолжить, то всё продолжается. Что делать? Как это обработать?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
22.04.2013, 20:06
Помогаю со студенческими работами здесь

Как оптимизировать на чтение, если много оперативки?
Есть базы суммарным размером гиг 30. Есть сервер виртуальный с 60 гигами памяти. Как мне сделать так чтобы постгрес затолкал базы в память...

Много методов или много классов. Что лучше?
Имеется библиотека(ActiveX DLL), в которую, в своё время, было решено складировать функции, вызваемые извне(точнее, основным модулем)....

Конкатенация потребляет много памяти, как можно оптимизировать?
Конкатенация потребляет много памяти. Если учесть, что символ занимает 2 байта, то результирующая строка кода должна занимать около 20 МБ,...

Где и как используется оператор elseif?
//Лирическое вступление Изучая многие языки программирования, прихожу к выводу - что неопределенность это плохо. Неопределенность - это...

Используется много памяти
Здравствуйте! Недавно откатил Windows 8.1 на Windows 7. После установки новой винды, решил поставить по больше оперативки. Поставил 2...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит переходные токи и напряжения на элементах схемы. . . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru