Как развиваться в стеке с Nim?

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

Из какого подмножества Nim я могу работать, чтобы добиться только выделения памяти в стеке? Я предполагаю, что могу сказать, что это сработало по отсутствию memset или memcpy в кешированном C-коде.

3 ответа

Если вы действительно хотите обойтись без сборки мусора, вам нужно использовать --gc с none параметр, как описано в Руководстве пользователя Nim Compiler. none Параметр отключает сборщик мусора, оставляя вас наедине. Обычно это означает, что любые строковые операции будут выдавать предупреждение, потому что, несмотря на выделение памяти, никто не освобождает ее позже:

proc main() =
  let x = 5
  echo "Hello " & $x & " there"

main()

Если вы скомпилируете этот маленький тест с nim c --gc:none -r test.nim вы получите предупреждение gc:

test.nim(3, 19) Warning: '$ x' uses GC'ed memory [GcMem]
test.nim(3, 22) Warning: '&("Hello ", $ x, " there")' uses GC'ed memory [GcMem]

Это может помочь вам определить, какие части Nim безопасны для использования в среде без GC, прямо или косвенно. Обратите внимание, однако, что некоторые операции могут быть переведены в фазу компиляции. Таким образом, следующий пример, обеспечивающий одинаковый вывод, безопасен для использования без GC, поскольку все const выражения распределяются статически сгенерированным кодом C:

proc main() =
  const x = 5
  echo "Hello " & $x & " there"

main()

Глядя внутрь nimcache В каталоге вы найдете источник, содержащий строку, подобную этой:

  STRING_LITERAL(TM_ipcYmBC9bj9a1BW35ABoB1Kw_2, "Hello 5 there", 13);

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

Не специфика Nim, не специфика GC, и я не собираюсь давать здесь разумный ответ, а совет по программированию, не зависящий от языка.

Стек ограничен MiB или 24 КБ на Android. Вы можете сделать это 8MiB, возможно, путем настройки манифестов влево и вправо.

Если у вас нет ОС, в реальном режиме и не виртуализированной памяти, возможно, у вас будет неограниченный стек.

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

Это дает 2 преимущества: отделение от стека вызовов и объем блоков. И неограниченная память.

Ограничение: в Linux ваши страницы будут заполнены нулями по требованию. Ядро лениво предоставляет страницы, чтобы вы могли заикаться в критическое время. Чтобы избежать этого, подготовьте один проход для записи 0xff на все пространство. Это будет иметь недостаток, заключающийся в том, что он не очень взаимодействует с другими процессами и потенциально разрушает кэш файловой системы. Но для приложений реального времени, которые обычно принимаются пользователями.

В настоящее время и строка, и тип seq требуют, чтобы GC работал правильно, даже если они имеют семантику типа значения. Это, однако, планируется изменить. Я просто не могу сказать тебе, когда это будет. И без этих двух типов Nim не был бы языком, который вы хотели бы использовать. Помимо этих типов Wrok во многом как в C++. Так что, если вы не используете ref типы не будет дальнейшего распределения для GC.

Другие вопросы по тегам