Что было бы лучше для одновременных задач на node.js? Волокна? Веб-рабочие? или Threads?

Я наткнулся на node.js когда-то и очень понравился. Но вскоре я узнал, что ему не хватало возможности выполнять задачи с интенсивным использованием процессора. Итак, я начал поиск в Google и получил ответы на эту проблему: Fibers, Webworkers and Threads (thread-a-gogo). Теперь, какой из них использовать, является путаницей, и один из них определенно нужно использовать - после чего какая цель иметь сервер, который просто хорош в IO и ничего больше? Предложения необходимы!

UPDATE:

Я думал о том, чтобы уйти поздно; просто нуждаясь в предложениях по этому поводу. Теперь, о чем я подумал, это: Пусть есть потоки (используя thread_a_gogo или, возможно, веб-работники). Теперь, когда нам нужно больше из них, мы можем создать больше. Но в процессе создания будет определенный предел. (не подразумевается системой, но, вероятно, из-за накладных расходов). Теперь, когда мы превысим предел, мы можем разблокировать новый node и начать создавать потоки поверх него. Таким образом, он может продолжаться до тех пор, пока мы не достигнем определенного предела (в конце концов, процессы тоже имеют большие накладные расходы). Когда этот предел будет достигнут, мы начнем задачи очередей. Всякий раз, когда поток становится свободным, ему назначается новая задача. Таким образом, он может идти плавно.

Итак, это то, о чем я думал. Это хорошая идея? Я немного новичок во всем этом процессе и потоках, поэтому у меня нет опыта. Пожалуйста, поделитесь своими мнениями.

Спасибо.:)

Ответ 1

Node имеет совершенно другую парадигму, и как только она будет правильно захвачена, легче увидеть этот другой способ решения проблем. Вам никогда не нужно несколько потоков в приложении Node (1), потому что у вас есть другой способ сделать то же самое. Вы создаете несколько процессов; но это очень сильно отличается от, например, как работает Apache Web Server Prefork mpm.

Пока давайте подумаем, что у нас есть только одно ядро ​​ЦП, и мы разработаем приложение (в Node) для выполнения некоторой работы. Наша задача - обработать большой файл, работающий по содержимому побайтно. Лучший способ для нашего программного обеспечения - начать работу с начала файла, следовать за ним побайтам до конца.

- Эй, Хасан, я полагаю, вы либо новичок, либо очень старая школа со времен моего деда! Почему бы вам не создать несколько потоков и сделать их намного быстрее?

- О, у нас есть только одно ядро ​​процессора.

- И что? Создайте поток людей, сделайте это быстрее!

- Это не работает. Если я создам потоки, я буду делать это медленнее. Потому что я добавлю много накладных расходов на систему для переключения между потоками, пытаясь дать им простое количество времени и внутри моего процесса, пытаясь установить связь между этими потоками. В дополнение ко всем этим фактам мне также придется подумать о том, как разделить одну работу на несколько частей, которые можно сделать параллельно.

- Хорошо, я вижу, вы бедны. Позвольте использовать мой компьютер, он имеет 32 ядра!

- Вау, ты классный мой дорогой друг, спасибо тебе большое. Я ценю это!

Затем мы возвращаемся к работе. Теперь у нас есть 32 ядра процессора благодаря нашему богатому другу. Правила, которые мы должны соблюдать, только что изменились. Теперь мы хотим использовать все это богатство, которое нам дано.

Чтобы использовать несколько ядер, нам нужно найти способ разделить нашу работу на части, которые мы можем обрабатывать параллельно. Если это не было Node, для этого мы будем использовать потоки; 32 потока, по одному для каждого ядра процессора. Однако, поскольку мы имеем Node, мы создадим 32 Node процесса.

Потоки могут быть хорошей альтернативой процессам Node, возможно, даже лучшим способом; но только в определенном виде работы, где работа уже определена, и мы полностью контролируем, как ее обрабатывать. Кроме этого, для любого другого рода проблемы, где работа идет снаружи так, как мы не имеем контроля над и мы хотим, чтобы ответить как можно быстрее, Node путь неоспоримо выше.

- Эй, Хасан, ты все еще работаешь однопоточно? Что с тобой случилось, мужик? Я только что предоставил вам то, что вы хотели. У вас больше нет оправданий. Создавайте потоки, чтобы они работали быстрее.

- Я разделил произведение на части, и каждый процесс будет работать на одной из этих частей параллельно.

- Почему вы не создаете потоки?

- Извините, я не думаю, что это можно использовать. Вы можете взять свой компьютер, если хотите?

- Ничего, я классный, я просто не понимаю, почему вы не используете потоки?

- Спасибо за компьютер.:) Я уже разделил произведение на части, и я создаю процессы для работы над этими частями параллельно. Все процессорные ядра будут полностью использованы. Я мог бы сделать это с помощью потоков вместо процессов; но Node имеет такой путь, и мой босс Парт Тхаккар хочет, чтобы я использовал Node.

- Хорошо, дайте мне знать, если вам нужен другой компьютер.: Р

Если я создам 33 процесса, вместо 32, планировщик операционной системы будет приостанавливать поток, запускать другой, приостанавливать его после нескольких циклов, снова запускать другой... Это лишние накладные расходы. Я не хочу этого. Фактически, в системе с 32 ядрами я бы даже не хотел создавать ровно 32 процесса, 31 может быть приятнее. Потому что это не просто мое приложение, которое будет работать в этой системе. Оставляя небольшую комнату для других вещей, может быть хорошо, особенно если у нас есть 32 номера.

Я считаю, что мы на одной странице теперь полностью используем процессоры для задач с интенсивным использованием ЦП.

- Хм, Хасан, мне очень жаль насмехаться над вами. Полагаю, теперь я понимаю тебя лучше. Но есть еще кое-что, что мне нужно для объяснения: что все жужжит для запуска сотен потоков? Я читаю везде, что потоки намного быстрее создают и тупые, чем процессы разветвления? Вы используете процессы fork вместо потоков, и вы считаете, что это самое высокое значение, которое вы получите с помощью Node. Тогда Node не подходит для такого рода работ?

- Не беспокойся, я тоже классный. Все говорят так, поэтому я думаю, что привык слышать их.

- Итак? Node не подходит для этого?

- Node отлично подходит для этого, даже если потоки могут быть хорошими. Что касается накладных расходов на поток/процесс; на то, что вы повторяете много, каждая миллисекунда считается. Тем не менее, я создаю только 32 процесса, и потребуется немного времени. Это произойдет только один раз. Это не будет иметь никакого значения.

- Когда я хочу создать тысячи потоков, то?

- Вы никогда не хотите создавать тысячи потоков. Тем не менее, в системе, которая выполняет работу, которая поступает извне, например, веб-сервер, обрабатывающий HTTP-запросы; если вы используете поток для каждого запроса, вы будете создавать много потоков, многие из них.

- Node отличается, правда? Правильно?

- Да, точно. Здесь Node действительно сияет. Подобно потоку намного легче процесса, вызов функции намного легче, чем поток. Node вызывает функции вместо создания потоков. В примере веб-сервера каждый входящий запрос вызывает вызов функции.

- Хм, интересно; но вы можете запускать только одну функцию одновременно, если вы не используете несколько потоков. Как это может работать, когда на веб-сервер приходит много запросов?

- Вы совершенно правы в том, как работают функции, по одному, а не два параллельно. Я имею в виду, что в одном процессе одновременно выполняется только одна область кода. Планировщик ОС не приходит и не приостанавливает эту функцию и переключается на другую, если она не приостанавливает процесс, чтобы дать время другому процессу, а не другой поток в нашем процессе. (2)

- Тогда как процесс обрабатывает 2 запроса одновременно?

- Процесс может обрабатывать десятки тысяч запросов за раз, пока наша система имеет достаточно ресурсов (оперативная память, сеть и т.д.). Как работают эти функции, ОСНОВНАЯ РАЗЛИЧИЯ.

- Хм, мне теперь нужно возбуждать?

- Может быть:) Node запускает цикл по очереди. В этой очереди находятся наши задания, то есть вызовы, которые мы начали обрабатывать входящие запросы. Наиболее важным моментом здесь является то, как мы разрабатываем наши функции для запуска. Вместо того, чтобы начать обработку запроса и заставить вызывающего абонента ждать, пока мы закончим работу, мы быстро прекратим нашу функцию после выполнения приемлемого объема работы. Когда мы подошли к точке, где нам нужно подождать, пока другой компонент выполнит какую-то работу и вернет нам значение, вместо того, чтобы ждать этого, мы просто завершаем нашу функцию, добавляя остальную часть работы в очередь.

- Звучит слишком сложно?

- Нет, я мог бы казаться сложным; но сама система очень проста и имеет смысл.

Теперь я хочу прекратить ссылаться на диалог между этими двумя разработчиками и закончить свой ответ после последнего быстрого примера того, как эти функции работают.

Таким образом, мы делаем то, что обычно планировал Scheduler. В какой-то момент мы приостанавливаем нашу работу и позволяем запускать другие вызовы функций (например, другие потоки в многопоточной среде), пока мы не вернемся к нашей очереди. Это намного лучше, чем оставить работу OS Scheduler, которая пытается дать время для каждого потока в системе. Мы знаем, что мы делаем намного лучше, чем OS Scheduler, и мы должны прекратить работу, когда мы должны остановиться.

Ниже приведен простой пример, когда мы открываем файл и читаем его, чтобы выполнить некоторую работу над данными.

Синхронный путь:

Open File
Repeat This:    
    Read Some
    Do the work

Асинхронный путь:

Open File and Do this when it is ready: // Our function returns
    Repeat this:
        Read Some and when it is ready: // Returns again
            Do some work

Как вы видите, наша функция просит систему открыть файл и не дожидаться его открытия. Он заканчивается, предоставляя следующие шаги после того, как файл готов. Когда мы вернемся, Node выполняет другие вызовы функций в очереди. После выполнения всех функций цикл события перемещается в следующий ход...

Таким образом, Node имеет совершенно другую парадигму, чем многопоточная разработка; но это не означает, что ему не хватает вещей. Для синхронного задания (где мы можем определить порядок и способ обработки), он работает так же, как и многопоточный parallelism. Для работы, которая поступает извне, как запросы на сервер, она просто превосходит.


(1) Если вы не создаете библиотеки на других языках, таких как C/С++, в этом случае вы по-прежнему не создаете потоки для разделения заданий. Для этой работы у вас есть два потока, один из которых продолжит общение с Node, а другой - реальную работу.

(2) Фактически, каждый процесс Node имеет несколько потоков по тем же причинам, о которых я упомянул в первой сноске. Однако это не похоже на то, как 1000 потоков выполняют аналогичные работы. Эти дополнительные потоки предназначены для того, чтобы принимать события IO и обрабатывать обмен сообщениями между процессами.

ОБНОВЛЕНИЕ (Отвечая на хороший вопрос в комментариях)

@Марк, благодарю вас за конструктивную критику. В парадигме Node у вас никогда не должно быть функций, которые занимают слишком много времени, пока все остальные вызовы в очереди не будут запущены один за другим. В случае дорогостоящих вычислительных задач, если мы посмотрим на картину в полном объеме, мы видим, что это не вопрос "Должны ли мы использовать потоки или процессы?" но вопрос "Как мы можем сбалансированно разделить эти задачи на подзадачи, чтобы мы могли их параллельно запускать, используя несколько процессоров в системе?" Скажем, мы будем обрабатывать 400 видеофайлов в системе с 8 ядрами. Если мы хотим обрабатывать один файл за раз, нам нужна система, которая будет обрабатывать разные части одного и того же файла, и в этом случае, возможно, многопоточная система с одним процессом будет легче создавать и даже более эффективно. Мы все еще можем использовать Node для этого, запустив несколько процессов и передавая сообщения между ними, когда требуется совместное использование/обмен данными. Как я уже говорил, многопроцессорный подход с Node является также многопоточным подходом в таких задачах; но не более того. Опять же, как я уже говорил, ситуация, когда Node светит, когда мы имеем эти задачи, поступающие как входные данные в систему из нескольких источников, поскольку одновременное использование многих соединений намного легче в Node по сравнению с потоком за соединение или процесс -подключительная система.

Как для вызовов setTimeout(...,0); иногда предоставляя перерыв во время трудоемкой задачи, чтобы позволить вызовам в очереди иметь свою долю обработки, может потребоваться. Разделение задач по-разному может спасти вас от них; но все же, это не хак, это просто то, как работают очереди событий. Кроме того, использование process.nextTick для этой цели намного лучше, поскольку, когда вы используете setTimeout, вычисление и проверка прошедшего времени будут необходимы, а process.nextTick - это просто то, что мы действительно хотим: "Эй, задача, вернуться к концу в очереди, вы использовали свою долю!"

Ответ 2

(Обновление 2016: веб-работники входят в io.js - a Node.js fork Node.js v7 - см. ниже.)

(Обновление 2017: веб-рабочие не входят в Node.js v7 или v8 - см. ниже.)

Некоторое уточнение

Прочитав приведенные выше ответы, я хотел бы отметить, что в веб-работниках нет ничего, что противоречит философии JavaScript вообще и Node в частности в отношении concurrency. (Если бы это было, это не было бы даже обсуждено WHATWG, а тем более реализовано в браузерах).

Вы можете думать о веб-работнике как об облегченной микросервисе, к которому обращаются асинхронно. Ни одно государство не используется. Никаких проблем с блокировкой не существует. Нет блокировки. Синхронизация не требуется. Как и при использовании службы RESTful из вашей программы Node, вы не беспокоитесь, что она теперь "многопоточна", потому что служба RESTful не находится в том же потоке, что и ваш собственный цикл событий. Это просто отдельная служба, к которой вы обращаетесь асинхронно, и это важно.

То же самое с веб-работниками. Это просто API для связи с кодом, который работает в совершенно отдельном контексте и находится ли он в разных потоках, разных процессах, разных группах, зонах, контейнерах или разных машинах совершенно неактуальен из-за строго асинхронного, неблокирующего API, со всеми данными, переданными по значению.

Фактически веб-работники концептуально идеально подходят для Node, который, как многие люди не знают, попутно использует потоки довольно сильно, а на самом деле "все работает параллельно, кроме вашего кода" - см.:

Но веб-работникам даже не нужно реализовывать потоки. Вы можете использовать процессы, зеленые потоки или даже службы RESTful в облаке - до тех пор, пока используется API веб-работников. Вся красота передающего сообщения API с помощью семантики вызова по значению заключается в том, что основная реализация практически не имеет значения, поскольку детали модели concurrency не будут раскрыты.

Однопоточный цикл событий идеально подходит для операций с привязкой к вводу/выводу. Это не так хорошо работает для операций с ЦП, особенно для длинных. Для этого нам нужно создать больше процессов или использовать потоки. Управление дочерними процессами и межпроцессное взаимодействие переносимым образом может быть довольно сложным, и его часто считают излишним для простых задач, в то время как использование потоков означает работу с блокировками и проблемами синхронизации, которые очень трудно сделать правильно.

Часто рекомендуется разделять длительные операции, связанные с ЦП, на более мелкие задачи (что-то вроде примера в разделе "Оригинальный ответ" моего ответа на Ускорение setInterval), но это не всегда практично и не использует больше одного ядра процессора.

Я пишу это, чтобы уточнить комментарии, которые в основном говорят о том, что веб-рабочие были созданы для браузеров, а не серверов (забывая, что в JavaScript можно сказать почти все).

Node модули

Существует несколько модулей, которые должны добавить веб-работников в Node:

Я не использовал ни одного из них, но у меня есть два быстрых наблюдения, которые могут иметь значение: по состоянию на март 2015 года node -webworker на последнем месте был обновлен 4 года назад, а node -webworker-threads на последнем месте был обновлен месяц назад. Также я вижу в примере использования node -webworker-threads, что вы можете использовать функцию вместо имени файла в качестве аргумента для конструктора Worker, который, кажется, может вызвать тонкие проблемы, если он реализован с использованием потоков, которые делят память ( если функции не используются только для его метода .toString() и в других случаях скомпилированы в другой среде, и в этом случае это может быть хорошо - мне нужно глубже вникать в это, просто поделившись своими наблюдениями здесь).

Если есть какой-либо другой соответствующий проект, который реализует API веб-работников в Node, оставьте комментарий.

Обновление 1

Я еще не знал этого на момент написания, но, кстати, за один день до того, как я написал этот ответ Веб-рабочие были добавлены в io.js.

(io.js является вилкой Node.js - см.: Почему io.js решил развить Node.js, интервью InfoWorld с Майкелем Роджерсом, для получения дополнительной информации.)

Не только доказывает, что в веб-работниках нет ничего, что противоречит философии JavaScript вообще и Node, в частности, в отношении concurrency, но это может привести к тому, что веб-работники станут гражданами первого класса в серверный JavaScript, такой как io.js(и, возможно, Node.js в будущем) так же, как он уже находится на клиентском JavaScript во всех современных браузерах.

Обновление 2

В обновлении 1 и мой твит Я имел в виду io.js тянуть запрос № 1159 который теперь перенаправляется на Node PR # 1159 который был закрыт 8 июля и заменен на Node PR # 2133 - который по-прежнему открыт. Существует некоторая дискуссия, проходящая под этими запросами на растяжение, которые могут предоставить более подробную информацию о статусе веб-работников в io.js/ Node.js.

Обновление 3

Последняя информация - благодаря NiCk Newman для публикации в комментарии: Существует работники: первоначальная реализация фиксация Петкой Антоновым от 6 сентября 2015 г. которые могут быть загружены и опробованы в это дерево. Подробнее см. В комментариях NiCk Newman.

Обновление 4

По состоянию на май 2016 последние комментарии по прежнему открытым PR # 2133 - работники: первоначальная реализация были 3 месяцев. 30 мая Matheus Moreira попросил меня опубликовать обновление этого ответа в комментариях ниже, и он спросил о текущем статусе этой функции в PR комментарии.

Первые ответы в PR-дискуссии были скептичны, но позже Бен Noordhuis написал, что "получение этого объединения в той или иной форме в моем списке задач для v7".

Все остальные комментарии, казалось, были вторыми, и, по состоянию на июль 2016 года, кажется, что Веб-работники должны быть доступны в следующей версии Node, версии 7.0, которую планируется выпустить на Октябрь 2016 (не обязательно в форме этого точного PR).

Спасибо Matheus Moreira за то, что он указал на комментарии и оживил обсуждение GitHub.

Обновление 5

По состоянию на Июль 2016 имеется несколько модулей на npm, которые ранее не были доступны - для получения полного списка соответствующих модулей выполните поиск npm для рабочих, веб-работников и т.д. Если что-то в особенности работает или не работает для вас, отправьте комментарий.

Обновление 6

По состоянию на Январь 2017 маловероятно, что веб-работники будут объединены в Node.js.

Запрос на вытягивание # 2133 работники: первоначальная реализация Петкой Антоновым с 8 июля 2015 года была наконец закрытый от Ben Noordhuis 11 декабря 2016 года, который прокомментировал, что "поддержка многопоточности добавляет слишком много новых отказов для недостаточной выгоды" и "мы также можем выполните это с использованием более традиционных средств, таких как разделяемая память и более эффективная сериализация".

Для получения дополнительной информации см. комментарии к PR 2133 на GitHub.

Еще раз спасибо Matheus Moreira за то, что он указал в комментариях.

Ответ 3

Я пришел из старой школы мысли, где мы использовали многопоточность, чтобы быстро сделать программное обеспечение. За последние 3 года я использовал Node.js и большой сторонник этого. Как подробно объяснил, как работает node и концепция асинхронной функциональности. Но позвольте мне добавить несколько вещей здесь.

В прежние времена с одиночными ядрами и более низкими тактовыми частотами мы пытались различными способами сделать работу программного обеспечения быстрой и параллельной. в DOS дней мы используем для запуска по одной программе за раз. В окнах мы запускали несколько приложений (процессов) вместе. Концепции, такие как упреждающие и не превентивные (или совлокальные), где протестированы. теперь мы знаем, что превентивный ответ был ответом на лучшую задачу многопроцессорности на одноядерных компьютерах. Наряду с концепциями процессов/задач и переключения контекста. Чем концепция потока для дальнейшего снижения нагрузки на переключение контекста процесса. Поток, который придумал как легкий вес, альтернативный нерестам новых процессов.

Так как это или нет сигнальная нить или не многоядерная или одноядерная, ваши процессы будут выгружены ОС и вырезаны по времени.

Nodejs - это единственный процесс и обеспечивает механизм async. Здесь рабочие места отправляются под управлением ОС для выполнения задач, пока мы ожидаем в цикле событий для завершения задачи. Как только мы получим зеленый сигнал от ОС, мы выполняем все, что нам нужно. Теперь в некотором роде это совместная/непредостанная многозадачность, поэтому мы никогда не должны блокировать цикл событий в течение очень длительного периода времени, иначе мы будем очень быстро деградировать наше приложение.
Поэтому, если есть когда-либо задача, которая блокирует природу или очень трудоемка, нам придется разветкить ее на превентивный мир ОС и потоков. есть хорошие примеры этого в libuv documentation. Кроме того, если вы прочтете документацию, вы обнаружите, что FileI/O обрабатывается в потоках в Node.js.

Итак, во-первых, это все в дизайне нашего программного обеспечения. Во-вторых, контекстное переключение всегда происходит независимо от того, что они говорят вам. Тема там и все еще существует по какой-то причине, причина в том, что они быстрее переключаются между процессами.

Под капотом в Node.js все его С++ и потоки. И node предоставляет С++ способ расширить свою функциональность и ускорить работу, используя потоки, где они должны, то есть блокировать такие задачи, как чтение из источника записи в источник, большой анализ данных и т.д.

Я знаю, что ответ hasanyasin является принятым, но для меня потоки будут существовать независимо от того, что вы говорите, или как вы скрываете их за сценариями, во-вторых, никто не просто ломает вещи в потоки только для скорости, в основном это делается для блокировки задач. И нити находятся в задней части Node.js, поэтому, прежде чем полностью избивать многопоточность, она верна. Кроме того, потоки отличаются от процессов, и ограничение того, что процессы node на ядро ​​не точно применимы к числу потоков, потоки похожи на вспомогательные задачи для процесса. на самом деле нитки выиграли, т отображаются в диспетчере задач Windows или в верхней команде linux. в очередной раз они имеют меньший вес, чем процессы

Ответ 4

Я не уверен, что в этом случае важны веб-работники, они являются технологиями на стороне клиента (запускаются в браузере), а node.js запускается на сервере. Волокна, насколько я понимаю, также блокируют, т.е. Они являются добровольной многозадачностью, поэтому вы можете их использовать, но должны управлять контекстными переключателями самостоятельно через yield. Темы могут быть на самом деле то, что вам нужно, но я не знаю, насколько они зрелы в node.js.

Ответ 5

Во многих мнениях разработчиков Node одна из лучших частей Node на самом деле является однопоточной. Нити представляют собой множество трудностей с общими ресурсами, которые Node полностью избегает, не делая ничего, кроме неблокирующего IO.

Чтобы не сказать, что Node ограничивается одним потоком. Это просто, что метод получения threaded concurrency отличается от того, что вы ищете. Стандартный способ борьбы с потоками состоит в cluster, который поставляется со стандартом Node. Это более простой подход к потокам, чем ручное обращение с ними в вашем коде.

Для работы с асинхронным программированием в вашем коде (как и во избежание вложенных пирамид обратного вызова), компонент [Future] в Fibers библиотека - достойный выбор. Я также предлагаю вам проверить Asyncblock, который основан на Fibers. Волокна хороши, потому что они позволяют скрыть обратный вызов, дублируя стек, а затем перепрыгивая между стеками по одному потоку по мере необходимости. Экономит вас от настоящих потоков, предоставляя вам преимущества. Недостатком является то, что трассировки стека могут быть немного странными при использовании Fibers, но они не так уж плохи.

Если вам не нужно беспокоиться об асинхронных материалах и больше заинтересованы в том, чтобы делать много обработки без блокировки, простой вызов process.nextTick(обратный вызов) каждый раз в то время - это все, что вам нужно.

Ответ 6

Возможно, вам поможет дополнительная информация о том, какие задачи вы выполняете. Зачем вам (как вы упомянули в своем комментарии к ответу genericdave) нужно создать много тысяч из них? Обычный способ сделать это в Node - это запустить рабочий процесс (используя fork или какой-либо другой метод), который всегда запускается и может быть передан при использовании сообщений. Другими словами, не запускайте нового работника каждый раз, когда вам нужно выполнить любую задачу, которую вы выполняете, но просто отправляйте сообщение уже запущенному рабочему и получите ответ, когда это будет сделано. Честно говоря, я не вижу, что запуск многих тысяч реальных потоков будет очень эффективным, вы все еще ограничены вашими процессорами.

Теперь, сказав все это, я много работал с Hook.io в последнее время, который, похоже, очень хорошо работает для этот вид задач по загрузке в другие процессы, возможно, он может выполнить то, что вам нужно.