Node js server side javascript грузит процессор
We're having a problem where every once in a while one of our environments our node app runs on 100% CPU. The server isn't very active and usually runs on 0%-2% CPU. I was wondering what are the common issues that might cause this problem and what would be the best way to find out what causing this issue.
node version 0.8.14
ubuntu 11.10
Intel(R) Xeon(R) CPU E5645 @ 2.40GHz
Node packages used:
Ниасилил?
Node.js — неприятное ПО, и я его использовать не буду.
5 Answers 5
You can profile your app with node-tick.
- Install node-tick by npm -g install tick
- Run your app with enabled profile node --prof ./app.js
- After some time with CPU 100% usage stop your app
- You can see v8.log in your app directory, now you can read it with node-tick-processor
- Run node-tick-processor and explain results
Oh man, this helped me discover that I removed a module while also requiring it in a service. Good grief.
UPDATE 2019 !!
You better use the built in --prof-process to process v8 profiling data, the generated file is no longer v8.log and node-tick-processor won't help you much, so to profile your app and read the v8 profiling data you can proceed as follows:
Node will generate a file with a name like this isolate-0x103800000-v8.log in your current directory, now you use this file to generate a profiling report
Constantly running at 100% CPU is typical for infinite loop. This is a real problem in singlethreaded nodejs but unfortunately there is a lack of info on it.
Eventually I have found the only useful article: How to track the deadloop in nodejs:
Connect to you server via SSH. Identify nodejs process id (let it be 4702, for example). Now, let’s tell the process to listen for debugging requests. Yes, we’re using a command called kill. No, we’re not killing the process. We’re sending it a different signal.
Once you do this, the process is open to a debugger connection. In fact, it will print a special URL to its console log, and you can open that URL in Chrome to debug the process! But, maybe you don’t want to drill a hole through a firewall and a container configuration just to make that connection. Yeah, me neither. So let’s debug at the command line instead:
You’ll see this prompt:
And you get back:
Yes! We have our first hint. The app was executing line 555 in file something.js. That might be enough to see the bug right away. But usually we need more information than that. You can type backtrace to get a complete stack trace:
Если и есть что-то, что веб-разработчики любят, так это знать что-то, что лучше традиционного. Но традиционное является таковым по одной причине: это дерьмо работает. Что-то давно беспокоило меня во всей этой шумихе вокруг Node.js, но у меня не было времени разобраться, что именно, пока я не прочитал полный боли в жопе пост от Райана Дала, создателя Node.js. Я бы забыл его, как любое очередное нытьё какого-то осла о том, что Unix слишком сложен. Но, как полицейскому, который, жопой чуя, что что-то не так с этой семьёй в микроавтобусе, останавливает его и находит пятьдесят килограммов героина, мне показалось, что что-то не так с этой слезливой историей, и возможно, просто возможно, он понятия не имеет, что делает, и много лет программирует, никем не контролируемый.
Поскольку вы читаете это, вы, возможно, уже поняли, что моя догадка подтвердилась.
Node.js — это опухоль на программистском сообществе, не только оттого, что он совершенно безумен, но и оттого, что люди, использующие его, инфицируют других людей, не умеющих думать самостоятельно, пока, в конце концов, каждый встречающийся мне мудак не начинает читать проповеди об event loop'ах. Принял ли ты epoll в своё сердце?
Chrome DevTools Inspector
В первую очередь, это профайлер, встроенный в Chrome DevTools, который будет связываться с NodeJs приложением через WebSocket (стандартный порт 9229 ).
Запустите nodejs-приложение с флагом --inspect
(по умолчанию будет использоваться стандартный порт 9229 , который можно изменить через --inspect= ).
Если NodeJs сервер в докер-контейнере, нужно запускать ноду с --inspect=0.0.0.0:9229 и открыть порт в Dockerfile или docker-compose.yml
Откройте в браузере chrome://inspect
Найдите ваше приложение в “Remote Target” и нажмите “inspect” .
Откроется окно инспектора, схожее со стандартным “браузерным” Chrome DevTools.
Нас интересует вкладка “Profiler” , в которой можно записывать CPU профайл в любое время работы приложения:
После записи собранная информация будет представлена в удобном таблично-древовидном виде с указанием времени работы каждой ф-ии в ms и % от общего времени записи (см. ниже).
Возьмем для экспериментов простое приложение (можно склонировать отсюда), эксплуатирующее узкое место в либе cycle (используемой в другой популярной либе winston v2.x) для эмуляции JS кода с высокой нагрузкой на CPU.
Будем сравнивать работу оригинальной либы cycle и моей исправленной версии.
Установите приложение, запустите через npm run inspect . Откройте инспектор, начните запись CPU профайла. В открывшейся странице http://localhost:5001/ нажмите "Run CPU intensive task" , после завершения (алерта с текстом “ok”) завершите запись CPU профайла. В результате можно увидеть картину, которая укажет на наиболее прожорливые ф-ии (в данном случае — runOrigDecycle() и runFixedDecycle() , сравните их %):
1. CPU-профайлинг приложения. Инструменты
К счастью, у разработчиков есть удобные инструменты для обнаружения и визуализации “хот-спотов” загрузки CPU.
3. Обновляйте NodeJs (и npm-пакеты)
Иногда вы не виноваты :)
Смысл в том, что приложение запускает WebSocket-сервер (на socket-io) и запускает один дочерний процесс через child_process.fork() . Следующая последовательность действий гарантированно вызывает 100% загрузку 1 ядра CPU:
- К WS-северу подключается клиент
- Дочерний процесс завершается и пересоздается
- Клиент отключается от WS
Причем приложение все еще работает, Express сервер отвечает на запросы.
Вероятно, баг находится в libuv , а не в самой ноде. Истинную причину этого бага и исправляющий его коммит в changelog’ах я не нашел. Легкое “гугление” привело к подобным багам в старых версиях:
Решение простое — обновить ноду до v8.5.0+.
Разбираемся
- Если очень образно говоря, то Node.js это компонент, позволяющий использовать приложения на компьютере, который были написаны на языке JavaScript, который в принципе создан не для ПК, а для веб-приложений. На JavaScript пишут код (функции) для веб-сайтов, но не для компьютеров. А вот чтобы использовать на ПК возможности JavaScript — был придуман компонент Node.js. Но суть не в этом.
- Node.js Server-Side JavaScript может появиться после установки популярного софта, например от Адобе. Этот процесс позволяет обмениваться данными между программами (ПО Адобе содержит множество дочерних модулей). Также Node.js может использоваться для написания плагинов/дополнений.
- Также этот компонент может устанавливать соединение с интернетом. Зачем? Непонятно. Но важно понимать, что компонент может требоваться для работы некоторых модулей ПО, среди которых могут быть и модули проверки лицензии. Поэтому если заблокировать доступ в интернет — могут быть проблемы из-за невозможности проверить лицензию. Еще вместо лицензии может проверять наличие новой версии ПО.
Нашел комментарий как избавиться от процесса, однако предупреждаю — если будете делать, то только на свой страх и риск:
Что можно еще попробовать сделать? Можно попробовать радикально запретить работу процесса:
- Найдите Node.js Server-Side JavaScript в диспетчере задач.
- Нажмите правой кнопкой и выберите пункт Открыть расположение.
- Откроется папка с выделенным файлом. Процесс в диспетчере завершаем.
- Переименовываем файл, можно просто добавить символ нижнего пробела _. Если при переименовании будет ошибка — попробуйте утилиту Unlocker (умеет переименовывать/удалять заблокированные папки/файлы).
Однако этот способ может привести к ошибкам ПО, где используется компонент. Node.js может использоваться не только софтом Адобе, но и другим.
Но в целом, если в диспетчере такая картина:
И при этом доступ в интернет для Node.js Server-Side JavaScript не заблокирован — это НЕнормальное явление. Если у вас ПО лицензированное — нужно написать в техподдержку. Если качали ПО с торрентов, то такое ПО спокойно может быть глючным. Лучше конечно переустановить, скачав с официального сайта.
Надеюсь данная информация оказалась полезной. Удачи и добра, до новых встреч друзья!
NodeJs Profiler
Другой вариант — использование встроенного в NodeJs профайлера для создания отчетов о CPU производительности. В отличие от инспектора, он покажет данные за все время работы приложения.
Запустите nodejs-приложение с флагом --prof
В папке приложения будет создан файл вида isolate-0xXXXXXXX-v8.log , в который будут записываться данные о “тиках”.
Данные в этом файле неудобны для анализа, но из него можно сгенерировать человеко-читаемый отчет с помощью команды
node --prof-process
Пример такого отчета для тестового приложения выше тут
(Чтобы сгенерировать самому, запустите npm run prof )
2. Решение проблемы блокирующего JS-кода без инспектора
Предположим, так случилось, что в коде закрался бесконечный цикл или другая ошибка, приводящая к полной блокировке выполнения JS-кода на сервере. В этом случае единственный поток NodeJs будет заблокирован, сервер перестанет отвечать на запросы, а загрузка ядра CPU достигнет 100%. Если инспектор еще не запущен, то его запуск вам не поможет выловить виновный кусок кода.
В этом случае на помощь может прийти дебаггер gdb.
Для докера нужно использовать
--cap-add=SYS_PTRACE
и установить пакеты
apt-get install libc6-dbg libc-dbg gdb valgrind
Итак, нужно подключиться к nodejs процессу (зная его pid):
sudo gdb -p
После подключения ввести команды:
Я не буду вдаваться в подробности, что делает каждая команда, скажу лишь, что тут используются некоторые внутренние ф-ии движка V8.
В результате этого выполнение текущего блокирующего JS-кода в текущем “тике” будет остановлено, приложение продолжит свою работу (если вы используете Express, сервер сможет обрабатывать поступающее запросы дальше), а в стандартный поток вывода NodeJs-приложения будет выведен stack trace.
Он довольно длинный, но в нем можно найти полезную информацию — стек вызовов JS функций.
Находите строки такого вида:
Они должны помочь определить “виноватый” код.
Для удобства написал скрипт для автоматизации этого процесса с записью стека вызовов в отдельный лог-файл: loop-terminator.sh
Также см. пример приложения с его наглядным использованием.
Крах масштабируемости ждёт своего часа
Давайте начнём с самой ужасной лжи: Node.js масштабируем, потому что он «никогда не блокирует» (Радиация приносит пользу! Теперь в вашей зубной пасте!). На сайтe Node.js сказано:
В Node практически нет функций, напрямую выполняющих операции ввода-вывода, так что процесс никогда не блокируется. Из-за того, что ничего не блокируется, менее-чем-эксперты могут разрабатывать быстрые системы.
Это утверждение заманчиво, ободряюще и полностью, блядь, неверно.
Давайте начнём с определения, ведь ваша, хабровские всезнайки, специфика — педантизм. Вызов функции называется блокирующим, когда выполнение вызывающего потока будет приостановлено до завершения этой функции. Как правило, мы думаем об операциях ввода-вывода как о «блокирующих», например, если вызвать socket.read(), программа будет ожидать завершения этого вызова, так как ей нужно что-то сделать с возвращаемыми данными.
Вот вам забавный факт: вызов любой функции, использующей процессор, тоже блокирующий. Эта функция, вычисляющая N-ное число Фибоначчи, заблокирует текущий поток, потому что она использует процессор:
(Да, я знаю про замкнутое решение. А ты разве не должен сейчас репетировать перед зеркалом то, что скажешь, когда всё-таки решишься подойти к Ней?)
Посмотрим, что происходит с программой для Node.js, с вот этим маленьким бриллиантом в качестве обработчика запроса:
На моём предыдущем ноутбуке результат таков:
Время ответа — 5 секунд. Круто. Итак, мы все знаем, что JavaScript не офигенно быстрый язык, но что в этом страшного? А то, событийная модель Node и ёбнутые на всю голову фанатики заставили вас думать, что всё хорошо. Вот простенький псевдокод, показывающий, как работает event loop:
Это все, конечно, хорошо, если вы знаете, что вы делаете, но, применяя это для серверных задач, вы множите это дерьмо. Если этот цикл работает в том же потоке, что и handle_request, любой адекватный программист заметит, что обработчик запроса может заблокировать цикл, и без разницы, насколько асинхронна ваша библиотека.
Итак, учитывая вышесказанное, давайте посмотрим, как мой маленький node-сервер ведёт себя при самой скромной нагрузке — 10 запросов, 5 одновременных:
0.17 запросов в секунду. Зверь. Конечно, Node позволяет рожать дочерние процессы, но сейчас потоковая и событийная модель настолько сильно связаны, что вы уже получили гораздо большие проблемы, чем масштабируемость.
Учитывая оригинальную маркетинговую политику Node, я, чёрт побери, боюсь любых «быстрых систем», которые «менее-чем-эксперты» подарят этому миру.
9 Answers 9
Tools > Options > Text Editor > JavaScript/TypeScript > Language Service.
Uncheck 'Enable the new JavaScript language service'.
Restart Visual Studio
This appears to prevent the NodeJS process from starting.
This solution helped, should be upvoted. But you need to restart visual studio for this to take effect.
I did this, rebooted VS2017 an it still did not prevent "Node.js: Server-side JavaScript" from starting when I started VS2017. Its hogging about 800MB on my machine and I can no longer debug in Chrome.
Same problem here @Bill - disabling the TypeScript extension as per Gabriel's answer seems to have sorted it though.
I raised feedback on this issue:
I got response back from a MS Team - he directed me to this post:
The node.exe process has the command line:
Effectively I was told:
In VS 2017, several features are implemented in JavaScript. Node.js is used by Visual Studio to run that JavaScript. Among other things, Node is used to run the code that provides formatting and intellisense services when a user is editing TypeScript or JavaScript. This is a change from VS 2015.
It answers my question, but brings to light another - why do you need 1.4GB of memory to give me intellisense on JavaScript files . or is this one of the solutions that has been built into VS so it uses Less Memory so it doesn't hit the 2GB(4GB) limit of 32-bit processes? Questions questions questions.
Indeed it's a thing to make the main VS process more responsive and optimize performance by lazifying certain things like Intellisense into another process, and with more ram for each 32-bit process. But that doesn't matter for us in this case. What I've found is that Node consumes more memory if you have more source code files open and Intellisense enabled. If you're really running low on memory, experiment with disabling Intellisense and other features you could do without.
It has had the opposite effect for me and has made VS2017 so lazy (pun intended) that I'm going back to VS2015. I find it rediculous that MS have to use 3rd party external frameworks to do something as simple as Intellisense. That has always been one of their strengths . and now? I have disabled TypeScript and Node.js and if I just look at Chrome VS2017 hangs so badly I sometimes have to reboot. So back to Firefox and VS2015 for me, at least for now. And this is on an i7, 16GM RAM and all SSD setup with Win10 Pro. Shocking.
according to the post referenced here . Disabling the TypeScript extension is a work around for the moment, at least for me. Click Tools, Extensions and Updates, search for "TypeScript" and disable it. Restart Visual Studio.
You have to disable TypeScript support on Visual Studio:
Tools > Extensions and Updates > TypeScript for Microsoft Visual Studio > Disable
After that, just restart Visual Studio, and you are good to go.
Here is Bowden Kelly's answer:
The node process you are seeing is powering the JavaScript language service. You will see this process appear anytime you edit a JS file, TS file, or any file with JS/TS inside (html, cshtml, etc). This process is what powers IntelliSense, code navigation, formatting, and other editing features and it does this by analyzing the entire context of your project. If you have a lot of .js files in your project, this can get large, but more than likely the issue is that you have a lot of library files that are being analyzed. By default, we will scan every .js/.ts file in your project. But you can override this behavior and tune the language service to only focus on your code. To do this create a tsconfig.json in your project root with the following settings:
Once I added the folder with all my script libraries into the tsconfig.json file, life was good again.
After my soap box whinge in the previous answer, this seems to have saved the day. Such a simple thing yet so obscure and only took me three days of battling with VS2017 to finally find this!
Adding this file lead to all kinds of TypeScript errors when I built the project. Removed it and the errors went away.
The dirtiest workaround ever: just rename the ServiceHub.Host.Node.x86.exe to something else. Hasn't bothered me since. When (if) you actually need it, just rename it back.
Same trick works in Adobe Photoshop which also runs Node for some reason I haven't discovered in my usual workflow yet.
You can't just rename it and expect things to keep working. Who knew!
Apparently this renaming trick only works if you suspend VS process and kill Node, then resume VS. If you try to launch VS with Node exe file renamed, it will crash when opening a project with an "unknown hard error". Also, while working on an already loaded project, the lazy reference counter above methods and properties won't work because apparently that relies on Node being there somehow.
So it might be okay to just suspend the Node process and let Windows paging swap its memory out from ram onto the hard drive, without renaming the exe so you could start the VS again later without going through the renaming hassle. If you're willing to live with the consequences, that is.
Unfortunately, I think there's some code that will detect if the node process is unresponsive and launch a new one instead. I'm not familiar with that part of the VS code, but that's how it was described to me.
Something that can help the projects mitigate the nodejs weight: is to reassign the node version used under Tools > Options > Projects and Solutions > Web Package Management to an installed 64bit version. Studio will still launch its internal Node for a tsserver.js instance, but any typescript in project will default to the supplied version -- and this helped me firsthand.
Also, another time I found the language service to be running down, I discovered using a simple tsconfig.json above the directories used as repositories, and specify to skipLibCheck: true , and add node_modules to exclude -- tremendously helped along the service, and one file does all folders beneath it, regardless of direct project references. P.S. -- if you do want JavaScript intellisense support still, make sure to set the allowJs: true and noEmit: true option.
Lastly, verify in the Typescript Options under the Tools > Options > Text Editor > Javascript/Typescript > Project that it is not checked to Automatically compile Typescript files which are not part of a project since that can also tie up resources for auxillary 3rd party projects using node or typescript.
These are not fool-proof, each has to find their exact bottleneck, but I have found these have worked for me and my team more often than not
Node.js Server-Side JavaScript — компонент взаимодействия программ, может использоваться например в ПО Adobe для работы модулей/плагинов.
Простыми словами: так просто не ответить что это, почему? Node.js это библиотека, которая позволяет использовать возможности языка JavaScript на компьютере. При помощи этой библиотеке функционируют разные модули/плагины в разных программах. То есть у вас на ПК Node.js Server-Side JavaScript может быть например от Фотошопа или от другой программы.
Это блядский JavaScript
Возможно, худшее, что можно сделать с серверным фреймворком, — написать его на JavaScript.
Что это, я даже не…
Отрицая философию Unix, Node наказывает разработчика
Давным-давно стоявшие у истоков бородатые парни решили, что собирать в цепочку маленькие программы, каждая из которых выполняет специфическую задачу — отличная идея, а универсальным интерфейсом для них должен стать текст.
Если вы разрабатываете на платформе Unix, придерживаясь этого принципа, операционная система отблагодарит вас простотой и процветанием. К примеру, когда веб-приложения только появились, веб-приложение было просто программой, отдающей текст в стандартный вывод. Веб-сервер отвечал за принятие входящих запросов, выполнение этой программы и возврат результата клиенту. Мы назвали это CGI, и это был хороший способ выполнять работу, пока микро-оптимизаторы не сунули в него свои грязные пальцы.
Хотя, будем честны сами с собой, если вы Node-разработчик, вы, вероятно, запускаете приложение прямо из Node, запущенной в вашей экранной сессии под вашей учётной записью.
4. Используйте дочерние процессы
Если в вашем серверном приложении есть ресурсоемкий код, изрядно нагружающий CPU, хорошим решением может стать вынесение его в отдельный дочерний процесс. Например, это может быть серверный рендеринг React-приложения.
Говоря о производительности, другой не менее важной метрикой является потребление RAM. Существуют инструменты и техники для поиска утечек памяти, но это тема для отдельной статьи.
My app doesn't include any Node.JS libraries. I'm not able to figure out how to turn this Node.JS: Server-side Javascript process off. It's eating up too much memory for something I have no use for.
Is there a way to kill this aside from uninstalling VS 2017 and switching back to VS 2015?
Killing the main Process in Task Manager doesn't affect anything in VS, however if I go to the Details tab and kill the the individual running processes it crashes Visual Studio. I took a video of what happened after I killed the process and ran my local web page (Sorry for the quality, SO limited image size to 2MB):
I've ended that process and haven't seen any ill-effects. Web-compiler compiles LESS files without it.
@GlenLittle That does work, but like the cat. it came back. I'm wondering if it's something installed at the beginning and is always running. I just installed VS2017 on my lappy and it gave me the option to install the server. I'll update this when I test on it
Can you file a feedback item about this? There's a few different features in the web dev tools that use Node under the hood (such as the JSLint/CSSLint/etc) that might be involved here. These would show up for any web project, not just TypeScript or Node.
Update: от переводчика
Я тоже JavaScript-разработчик, давно с интересом присматривающийся к Node.js. Мне тоже обидно и больно за любимый язык. Однако, если отвлечься от боли, в вышеизложенном тексте можно найти смысл, аргументы и доказательства. Я бы очень хотел внятной дискуссии, ибо переводил я его только ради этого. По неизвестно кем установленной традиции, сообщу, что это мой первый перевод и всё такое.
Из-за однопоточной архитектуры Node.js важно быть настороже высокой производительности вашего приложения и избегать узких мест в коде, которые могут привести к просадкам в производительности и отнимать ценные ресурсы CPU у серверного приложения.
В этой статье речь пойдет о том, как производить мониторинг загрузки CPU nodejs-приложения, обнаружить ресурсоемкие участки кода, решить возможные проблемы со 100% загрузкой ядра CPU.
Читайте также: