Как получить местоположение в памяти переменной в Elixir?

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

есть ли способ получить адрес памяти переменной, на которую указывает, а не содержимое в этом месте памяти (т. е. разыменованное значение переменной)?


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

например, при обновлении кортежа все записи совместно используются между старым и новым кортежем, за исключением записи, которая была заменена. Другими словами, кортежи и списки в Elixir способны делиться своим содержимым.

1 ответов


TL; DR:

нет, вы не можете сделать ячейку памяти переменной.

Обсуждение

В принципе все копируется. Каждый процесс имеет свою собственную кучу. И так оно и есть.

на самом деле есть несколько базовых хаков скорости. Наиболее заметными являются

  • литералы, известные во время компиляции, ссылаются из глобальной кучи (что в некоторых случаях является огромным увеличением производительности).
  • бинарники более 64 байт ссылаются из глобальной кучи (что также приводит к тому, что двоичные файлы являются дырявой абстракцией, следовательно binary:copy/1,2).
  • обновления для большинства структур фактически не требуют копирования всей структуры (особый интерес представляет что происходит внутри карты) -- но сколько и когда копирование необходимо постоянно меняется, поскольку больше эффективности работы переходит во время выполнения.
  • сборка мусора происходит в процессе вот почему Erlang, похоже, имеет магически продвинутую инкрементную схему GC, но на самом деле имеет довольно скучную коллекцию кучи поколений внизу (в общем случае, то есть; подход на самом деле что-то вроде гибрида -- еще одна часть постоянно развивающегося ландшафта улучшений производительности EVM...).

Если вы собираетесь писать код для EVM, на любом языке,вы должны отказаться от идеи, что вы собираетесь перехитрить время работы. Это точно по той же причине, что попытка перехитрить большинство оптимизаций компилятора C (и особенно C++) является запрещенной практикой почти везде.

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

просто считать R20.0 объявление о выпуске. Идти в ногу с изменениями такого рода потребляет большую часть вашего времени разработки.

некоторые проекты делают попытку backhack выполнения всей своей целью. Считать витая, например. Такие проекты существуют специально для того, чтобы все эти (большие и нетривиальные) усилия не дублировались в каждом проекте в его нижнем течении. Имея это в виду, Erlang runtime, основной компилятор,LFE проект, проект эликсира, etc. сами являются местом для таких хаков скорости и абсолютно не в Нижнем клиентском коде. Счастливая вещь, чтобы отметить здесь (и да! У моей суровой истории счастливый конец!) заключается в том, что это именно то, что мы видим происходит.

примечание по "эффективности"

какую эффективность вы ищете? Циклы? Автобусное движение? Промахи кэша? финансовые затраты? I/O-ops устранение / обход / запись? Более общая выборочная обработка буфера? так далее.

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

случай, когда кто-то может захотеть "знать, что происходит", что я видел чаще всего, это случаи, когда люди пытаются использовать эликсир как " a faster Ruby " и написали не массово параллельную систему, а одну массивную однопоточную программу поверх EVM. Этот подход к написанию "быстрых" программ во время выполнения Erlang полностью упускает суть.

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

  • порт, написанный ржавчиной или C
  • NIF, написанный ржавчиной или C
  • высокопроизводительный вычислительный узел, что может взаимодействовать по сети с вашим основным узлом(узлами), написанным на каком-либо языке, идеально подходящем для вашей вычислительной задачи (Берт там очень полезно)
  • ожидание в течение года или двух для выполнения, чтобы принять больше улучшений производительности и аппаратного обеспечения, чтобы получить быстрее-скорость этой формы увеличения скорости - полное безумие для параллельных систем, особенно если вы работаете на собственном оборудовании (если вы работаете в "облаке", из конечно, эти улучшения в интересах поставщика но не тебе, а даже тогда дешевле позволить себе обчистить больше экземпляров, чем пытаться перехитрить среду выполнения)

написание отдельных программ (или NIFs) позволяет любому разработчику или команде, работающей над конкретной проблемой, работать в едином, унифицированном, едином проблемном пространстве, связанном только с выполнением любого контракта протокола, который они были переданы основным проектом. Это резко эффективнее, чем Эрланг или LFE или эликсира Дев/команды сальто между написанием некоторых Эрланг, то некоторые LangX, то некоторые Эрланг снова, переключение контекста как само собой разумеющееся (или хуже, переключение контекста от одного языка, на котором они являются специалистами и в котором они неопытны и наивны).

(имейте в виду также, что NIFs следует рассматривать как последнее средство и только считается, когда вы знаете ваше дело. В частности, дело в том, что ваша работа обработки мала для каждого вызова, предсказуема и хорошо ограничена, и что частые накладные расходы на вызов-это ваше узкое место больше, чем скорость обработки в NIF. NIFs уничтожают все гарантии безопасности выполнения. Разбитый NIF-это разбитое время выполнения - именно такая проблема, которую Erlang был разработан, чтобы избежать. Любой, кто чувствует себя достаточно комфортно в C, чтобы легкомысленно рекомендовать C NIFs повсюду явно не хватает опыта в C, чтобы писать эти Нифы!--24-->.)

на уровне проекта, проблемы эффективности, в первую очередь бизнес-решений, а не технические. Это плохое решение бизнеса (или управления сообществом, в случае сообщества FOSS), чтобы попытаться перехитрить среду выполнения.