Как узнать текущий размер стека функций в памяти, для лучшего контроля внутри кода?
Работаю над оптимизацией кода, и столкнулся в ходе оптимизации с переполнением стека. И ситуация такова, что даже вызов procces.nextTick является дорогим, и его приходится вызывать как можно реже. В связи с чем пришлось пока поставить счетчик и сбрасывать стек с помощью procces.nextTick каждый 1000 раз. Сами понимаете, что это такое себе. Поэтому идеально знать текущий размер стека, чтобы обрубать его при, допустим, 95% заполнении.
Отслеживать
13.7k 12 12 золотых знаков 43 43 серебряных знака 75 75 бронзовых знаков
задан 25 мар 2019 в 17:13
163 8 8 бронзовых знаков
Если возникла беда с переполнением стека, то проблема, скорее всего, в неверной логике, и в первую очередь следует её пересмотреть.
26 мар 2019 в 5:50
Проблемы в логике нет, ситуация такова: что нужно парсить гиговые логи, с крошечными записями. Изначально было 1.25 миллиона вызовов чтения fs.read на ГБ лога. Я снял 95% нагрузки на CPU созданием функции кеширования, но теперь может вызваться туча callback’ов подряд без разрыва стека и тем самым вызывать переполнение стека. Подгадать параметры кеша и тд. это не лучшее решение: что если код измениться, расшириться? Файл лога будет иной? Учитывая дороговизну process.nextTick(), было бы полезно к примеру иметь что-то подобное: getStackTrace() из JAVA.
26 мар 2019 в 15:01
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
var arrayContains = Array.prototype.indexOf ? function(arr, val) < return arr.indexOf(val) >-1; > : function(arr, val) < for (var i = 0, len = arr.length; i < len; ++i) < if (arr[i] === val) < return true; >> return false; >; function getCallStackSize() < var count = 0, fn = arguments.callee, functionsSeen = [fn]; while ( (fn = fn.caller) && !arrayContains(functionsSeen, fn) ) < functionsSeen.push(fn); count++; >return count; >
Отслеживать
ответ дан 25 мар 2019 в 22:13
perfect-elk perfect-elk
26 2 2 бронзовых знака
Суть интересная, но не работоспособная к сожалению. В редких случаях можно получить более менее приблизительный результат, но не более. В связи с тем, что функция будучи в рекурсии, ссылается сама на себя «.caller», нельзя узнать кто вызвал её, предшествуя перед рекурсией. А вне рекурсии нет смысла знать кол-во в стеке, ибо не достижимо. Если бы даже это и работало, была бы где нибудь ниша в отладке, но не в реальной рабочей рекурсии, ибо про производительность только молчать. Информации наскрести не выходит, совсем. Уже даже задумываюсь об перекомпиляции nodejs с доступом к счётчику ~_~
Как узнать размер стека?
Можно ли из проги на С++ узнать размер стека? Просто нужно реализовать рекурсивные вычисления, и узнать насколько глубоко может зайти рекурсивная функция.
anonymous
04.11.03 20:12:44 MSK
Как узнать размер стека?
sS ★★★★★
( 04.11.03 20:48:08 MSK )
Re: Как узнать размер стека?
LONGOBARD ★
( 04.11.03 21:19:11 MSK )
Re: Как узнать размер стека?
Если более точно, то около min(getrlimit(RLIMIT_STACK)+getrlimit(RLIMIT_DATA), getrlimit(RLIMIT_AS)).
Реально чуть меньше, т.к. часть памяти уже занята.
Murr ★★
( 04.11.03 22:35:36 MSK )
Ответ на: Re: Как узнать размер стека? от Murr 04.11.03 22:35:36 MSK
Re: Re: Как узнать размер стека?
Правда, для нитевого стека это всё не годится.
В этом случае можно поковырять как-нибудь так:
register unsigned long esp asm(«esp»);
И далее ковырять /proc/self/maps на предмет размера карты.
Правда, это не переносимо 🙁
Может кто-нибудь получше что предложит в этом случае .
Murr ★★
( 04.11.03 23:10:26 MSK )
Ответ на: Re: Re: Как узнать размер стека? от Murr 04.11.03 23:10:26 MSK
Re: Re: Re: Как узнать размер стека?
Хотя вот для POSIX Threads есть pthread_attr_getstacksize/pthread_attr_setstacksize.
Murr ★★
( 04.11.03 23:41:01 MSK )
Ответ на: Re: Re: Re: Как узнать размер стека? от Murr 04.11.03 23:41:01 MSK
По-моему, эти pthread_attr_getstacksize/setstacksize возвращают не совсем то. Как узнать attr для треда?
Debugger ★
( 05.11.03 10:40:29 MSK )
Ответ на: Re: от Debugger 05.11.03 10:40:29 MSK
Для библиотеки GNU C: #include
Размер общей памяти, использованной текущим процессом под стек
находится в элементе long ru_isrss структуры rusage,
заполняемой ф-ей int getrusage(int who, struct rusage* res);
где who = RUSAGE_SELF
Мягкий/жесткий предел размера стека
находится в элементе rlim_t rlim_cur/rlim_max структуры rlimit,
заполняемой ф-ей int getrlimit(int what, struct rlimit* res);
где what = RLIMIT_STACK
Размер стека
Структура стек (: добавить элемент в стек, удалить элемент из стека, получить значение с вершины стека, размер стека. )
Всем привет,ребят помогите пожалуйста с лабой,вообще без понятия про стеки:( Может кто то.
Как изменить размер стека
Доброго времени суток! Такой вопрос: как изменить размер стека в C++ или что использовать.
Как увеличить размер стека?
Есть быстрая сортировка — но выдает ошибку Stack overflow на массиве 100,7 Но работает на.
5231 / 3203 / 362
Регистрация: 12.12.2009
Сообщений: 8,112
Записей в блоге: 2
Написать костыль в виде асм-вставки?
1404 / 646 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
Kastaneda, не откажусь
5231 / 3203 / 362
Регистрация: 12.12.2009
Сообщений: 8,112
Записей в блоге: 2
Сообщение от Dani
Kastaneda, не откажусь
Вообще то я предложил вариант решения проблемы, а не написать готовый код
Вот, но это кривое решение, т.к. писал практически на коленке:
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
#include char* print_seq(int x) { if (!x) { char *p; // самое "глубокое" место на стеке, поэтому запоминаем указатель __asm { mov p, esp } return p; } char *p = print_seq(x-1); std::cout x " "; return p; } int main() { char *p1; __asm { mov p1, esp } char *p2 = print_seq(1000); std::cout std::endl "Stack size = " p1 - p2 std::endl; }
кривизна в том, что в рекурсивной функции еще создаются указатели, которые тоже занимают место на стеке, т.е. вывод не совсем правильный. Можно их вынести в global scope, а можно еще что-нибудь придумать, я только общую идею показал.
OberonCore
MODULE Fibonacci;
IMPORT StdLog;
PROCEDURE Do*;
VAR
a, b, c, i, n: INTEGER;
BEGIN
a := 0;
b := 1;
n := 9;
FOR i := 0 TO n DO
c := b;
b := a + b;
a := c;
StdLog.Int( c );
END;
END Do;
END Fibonacci.
все просто-выводит 10 чисел.Если однако убрать строчку n := 9; то программа начнет выводить бесконечное число цифр пока блекбох не зависнет с надписью «NOT RESPONDING».
Ясное дело что отведенный операционной системой стек оказался переполненым и ОС аварийно остановила программу.Вопрос: как узнать/вычислить сколько чисел максимально может выдать программа не зависнув?
Заголовок сообщения: Re: Узнать размер стека
Добавлено: Понедельник, 13 Январь, 2020 18:16
А причем здесь стек?
Заголовок сообщения: Re: Узнать размер стека
Добавлено: Понедельник, 13 Январь, 2020 19:03
Блэкбокс никогда не инициализирует переменные базовых типов внутри процедур.
Это важное свойство для скорости выполнения программ, а также для обучения начинающих программистов.
Поэтому ваша обязанность присвоить n какое-то значение.
Обнаружить такие ошибки в коде помогает команда Инфо -> Анализировать модуль
Снимок экрана от 2020-01-13 23-03-02.png [ 45.7 КБ | Просмотров: 5790 ]
В вашем случае n может быть очень большим, так как содержит «мусор» из оперативной памяти.
Поэтому программа выполняется очень долго. Но что хуже — её поведение не определено. ведь n может быть и отрицательным числом.
Заголовок сообщения: Re: Узнать размер стека
Добавлено: Понедельник, 13 Январь, 2020 19:22
Теперь, если понять ваш вопрос иначе.
Начнем с того, что Блэкбокс не завис, а продолжает выполнять ваше задание.
Но Windows думает, что он завис, поэтому показывает вам сообщение.
Он так думает, потому что Блэкбокс перестал отвечать на системные сообщения.
Чтобы ББ отвечал на них, и иногда обновлял интерфейс, надо в ваш цикл вставить вызов вот такой процедуры:
PROCEDURE ProcessMessages;
VAR msg: Win.MSG; res: INTEGER;
BEGIN
WHILE Win.PeekMessage(msg, 0, 0, 0, Win.PM_REMOVE) # 0 DO
res := Win.TranslateMessage(msg); res := Win.DispatchMessageA(msg)
END END ProcessMessages;
Получится вот такой код:
IMPORT StdLog, Win := WinApi;
PROCEDURE ProcessMessages;
VAR msg: Win.MSG; res: INTEGER;
BEGIN
WHILE Win.PeekMessage(msg, 0, 0, 0, Win.PM_REMOVE) # 0 DO
res := Win.TranslateMessage(msg); res := Win.DispatchMessageA(msg)
END END ProcessMessages;
PROCEDURE Do*;
VAR
a, b, c, i, n: INTEGER;
BEGIN
a := 0;
b := 1;
n := 900000;
FOR i := 0 TO n DO
c := b;
b := a + b;
a := c;
StdLog.Int( c );
IF i MOD 10000 = 0 THEN
ProcessMessages
END
END;
END Do;
Однако более правильное решение часто — это разбить вычисления на порции и организовать в очередь рекурсивно устанавливающихся событий.
Этот вопрос обсуждался тут:
viewtopic.php?f=1&t=130
Заголовок сообщения: Re: Узнать размер стека
Добавлено: Понедельник, 13 Январь, 2020 19:42
Иван Денисов писал(а):
В вашем случае n может быть очень большим, так как содержит «мусор» из оперативной памяти.
Поэтому программа выполняется очень долго.
Каким бы большим оно не было, это 32-битное число, программа не должна выполнятся слишком долго. Здесь дело в том, что слишком много пишется в журнал.
Заголовок сообщения: Re: Узнать размер стека
Добавлено: Понедельник, 13 Январь, 2020 19:46
Сочетание двух факторов
Сложность тела цикла + Число повторений цикла
А сложность может быть большой и без вывода в журнал.
Заголовок сообщения: Re: Узнать размер стека
Добавлено: Четверг, 09 Июль, 2020 09:48
Trurl писал(а):
Иван Денисов писал(а):
В вашем случае n может быть очень большим, так как содержит «мусор» из оперативной памяти.
Поэтому программа выполняется очень долго.
Каким бы большим оно не было, это 32-битное число, программа не должна выполнятся слишком долго. Здесь дело в том, что слишком много пишется в журнал.
А можно по подробней в этом плане?
Заголовок сообщения: Re: Узнать размер стека
Добавлено: Суббота, 11 Июль, 2020 13:12
Для любого 32-битного числа (кроме одного) собственно вычисления займут не более нескольких секунд. Но запись в журнал такого количества информации, а затем её отображение — большая нагрузка на систему.
Часовой пояс: UTC + 3 часа
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2023, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB