Пишу поискового бота, который запрашивает URL и забирает контент по этому URL'у для дальнейшей обработки. Процессор поддерживает возможность запуска ботов в несколько потоков, но здесь возникает вопрос, что будет быстрее — java threads или green threads (или легкие потоки, как в go).
Предположим я использую HttpClient для получения контента по определенному URL'у. Думаю, есть смысл создать Future задачи и замапить их на 100-200 (цифры от балды) java threads, через тот же thread pool. Тем самым, HttpClient будет работать в java threads запрашивая и получая контент по URL'у. С учетом пингов, примерно в 100мс, на эту работу может уйти до 600мс.
Если я правильно понял, то благодаря неблокируемому IO, поток с кодом HttpClient будет засыпать как минимум на 100мс, благодаря чему эти 100-200 потоков будут шустро отрабатывать, засыпая при ожидании данных, а затем просыпаясь для их приема.
И конечно, будет отдельный поток, который в бесконечном цикле обходит Future и проверяет, какие данные приняты и отправлять их в другой поток для обработки.
Правильно ли я разобрался? Может есть смысл для этого использовать Go c routines, заместо java с threads, будет ли это быстрее? Или на java можно сделать как-то хитрее?
UPDATE
Пинги могут быть и в 1000мс, а значит нужно создавать потоков чем больше, тем лучше, т.е. чтобы каждый поток держал соединение. А если юзать тредовый пул, скажем нитей на 100, то при 3000 ботах, будет работать медленно. Т.е. после освобождения нити, новый бот её захватит и заснет на 1000мс из-за IO, а очередь будет из 30 ботов на одну нить. А так, если каждому боту поток или хотя бы 2-3 бота в очередь на поток, то будет шустрее.
Вот только вопрос, какие пределы, скажем для какого-нибудь простого Core 2 Duo процессора? Какая будет разница в производительности, если юзать легкие нити go или делать тяжелые в java? 10 000 java потоков vs 10 000 goroutines c IO в 100-1000мс? Но видимо, здесь никто такое не тестил, буду сам разбираться сейчас.
А почему вы думаете, что треды явы настолько тяжелые? HttpClient сам по себе тяжелый наверно для задач просто скачивания :)
Я бы на вашем месте вместо извращений с go написал свой простой скачиватель контента вместо HttpClient, выхлопа будет больше. Насчет количества потоков Java — каждый поток занимает по умолчанию 2 Мб памяти при создании (можно уменьшить ключом JVM -Xss), вот и думайте сколько можно запустить
Я так думаю почитав про Erlang и про Go — как они хвалятся какие у них легкие потоки, не то что в java :) А почему вы думаете, что треды явы легкие? :)
Я уже заменил HttpClient на java.net.URL, получилось поднять производительность в два раза :)
Про -Xss, да я в курсе, но тут вопрос не в памяти, а в том, что куча потоков будет тратить кучу времени на переключение.
А если потоков одновременно будет 3000? Эти мизерные затраты могут стать часами, а то и днями при большом количестве данных. Плюс при пингах в 100-300мс, оптимально иметь 40 потоков на Core 2 Duo, а при больших пингах 1-2 сек нужно уже делать под 1000 потоков.
Вот мне и интересно в Go нужно также париться, настраивая пул на нужное количество потоков? Или там просто запустил горутины и оно само всё оптимально раскидала с учетом IO.
Знаете, слово «ping» имеет совсем другое значение.
Вероятно, вы имели в виду «latency».
Вы сперва сделайте хоть заготовку приложения на просто тредах, а потом уже будете смотреть, тормозит оно или нет, и потом уже при необходимости оптимизировать.
При решении подобной задачи, я бы обратил внимание на Akka (пример на хабре habrahabr.ru/post/125717/). Каждую таску с запросом оборачивал бы в класс актера. Можно было бы и самостоятельно заморачиваться многопоточностью, но тогда следовало бы иметь ввиду необходимость пулов потоков и т.д и т.п.