Зачем выделять переменную в rebol?

Я нашел такую ​​​​строку в каком-то коде Rebol:

dups: make block! 10000

Зачем вам использовать предварительное распределение в Rebol?

Что плохого в том, чтобы просто написать:

dups: copy []

person MaxV    schedule 16.04.2013    source источник


Ответы (4)


Во-первых: вы не «выделяете переменную» в Rebol, вы «предварительно выделяете буфер серии» (на который ссылается слово в вашем примере кода, но он может просто лежать в блоке).

Быстрый ответ: каждый раз, когда вы ВСТАВЛЯЕТЕ или ПРИСОЕДИНЯЕТЕ данные к серии, если буфер серии заполнен, менеджер памяти перераспределит серию в более крупную. Если вы расширяете серию несколько раз (например, добавляете данные в серию в цикле), если вы не выполняете предварительное выделение, вы можете в конечном итоге потреблять много дополнительной памяти для всех перераспределений и, возможно, в какой-то момент , также вызывая проходы сборщика мусора. Обычно это приводит к значительному замедлению выполнения программы и потреблению большого количества дополнительной памяти. Предварительное выделение буфера серии до размера, достаточного для хранения всех окончательных данных, позволит избежать всех этих проблем с памятью и производительностью.

В случае dups: copy [] вы выделяете минимальный буфер серии (с размером, вероятно, 8 или 16 слотов), поэтому, если все ваши данные не помещаются в этот буфер, ваша программа оплатит (тяжелую) стоимость перераспределения (с). Кроме того, [] — это предварительно выделенная литеральная серия минимального размера, которую вы просто используете в качестве шаблона для создания новой серии, поэтому лучше не тратить память впустую и вместо этого написать: dups: make block! 0, которая выделит блок! серия минимального размера без потери лишнего блока! ряд.

person DocKimbel    schedule 16.04.2013
comment
Используете ли вы предварительное размещение сегодня? Имеет ли смысл с современным ПК? - person MaxV; 17.04.2013
comment
Я только что проверил ›› a: make block! 10000 ›› b: копировать [] ›› дельта-время [цикл 10000 [добавить 1] ] == 0:00:00.004315 ›› дельта-время [цикл 10000 [добавить b 1] ] == 0:00:00.005795 - person MaxV; 17.04.2013
comment
Да, я всегда использую предварительное распределение, когда знаю, что мне нужно будет сделать много вставок, даже для небольших серий (в таком случае больше для поддержания хорошей практики кодирования, чем для эффективного выигрыша). Важно, когда ваша серия достаточно велика, независимо от имеющейся у вас вычислительной мощности, разница может достигать огромных размеров с огромными сериями (особенно при использовании памяти). - person DocKimbel; 17.04.2013
comment
Есть еще одна вещь с предварительным размещением. Если вы используете CALL/output для вставки вывода в строку, вам МОЖЕТ понадобиться предварительно выделить его, иначе иногда происходит сбой, если вывод слишком длинный. (в Windows) s: создайте строку! 1024 вызов/выход каталог /s c:\ s - person endo64; 18.04.2013

предварительное выделение буфера необходимо для низкоуровневой функции read-io

если вам нужно, например. доступ к точному коду ошибки при чтении данных можно использовать read-io вместо копирования на открытые порты.

read-io сравним с READ в языках Си. Вы предоставляете read-io предварительно выделенный фиксированный буфер и длину буфера. Если вы попробуете read-io с длиной буфера больше предварительно выделенной, вы делаете это на свой страх и риск.

person sqlab    schedule 14.06.2013
comment
Это не дает ответа на вопрос. Чтобы подвергнуть критике или запросить разъяснения у автора, оставьте комментарий под его сообщением — вы всегда можете прокомментировать свои собственные сообщения, и как только у вас будет достаточно reputation вы сможете комментировать любой пост. - person JMK; 14.06.2013
comment
Я думаю, что это ответ на то, почему вы используете .. но чтобы уточнить это - person sqlab; 15.06.2013

я только что проверил

>> a: make block! 10000
>> b: copy []
>> delta-time [loop 10000 [append a 1]]
== 0:00:00.004315
>> delta-time [loop 10000 [append b 1]]
== 0:00:00.005795

Разница чуть меньше сотой доли секунды.

Затем я перезапустил rebol и проверил:

>> a: make block! 10000
>> b: copy []
>> delta-time [loop 20000 [append a "test"]]
== 0:00:00.000238
>> delta-time [loop 20000 [append b "test"]]
== 0:00:00.000223

Нет предварительного размещения быстрее, чем предварительное размещение!

person MaxV    schedule 17.04.2013
comment
Пара замечаний: * DELTA-TIME не очень надежен * предварительное выделение неадекватного места не имеет смысла - person Ladislav; 17.04.2013
comment
Кроме того, что должен тестировать ваш перезапущенный пример? - person Ladislav; 17.04.2013
comment
Разница составляет чуть меньше сотой доли секунды. Так не следует сравнивать производительность, абсолютная разница во времени не имеет большого значения, вам нужно смотреть на относительную разницу во времени, поэтому: 0.005795 / 0.004315 увеличивает время выполнения примерно на 34 % без предварительного выделения памяти. - person DocKimbel; 17.04.2013
comment
Также вы должны тестировать с различными размерами серий, вы увидите, что чем больше серия, тем больше влияние на время выполнения, поэтому разрыв в производительности будет расти с размером серии. Еще один момент, который вы упустили, — это сравнение использования памяти в обоих случаях (вам нужно будет запускать каждый тест в новом сеансе Rebol). - person DocKimbel; 17.04.2013
comment
Что должен тестировать ваш второй пример? Это похоже на поврежденный код для меня. - person DocKimbel; 17.04.2013
comment
Если я не могу предсказать размер блока и предварительно выделить 10 000 позиций, то я добавляю 20 000 позиций... Кажется, лучше не делать предварительного распределения. - person MaxV; 18.04.2013
comment
Вы только доказали, что недостаточное предварительное выделение места вредно, это то, что мы пытаемся объяснить. - person DocKimbel; 19.04.2013

Я согласен с Ладиславом в том, что, вероятно, дельта-время ненадежно. Однако я не думаю, что современный ПК нуждается в предварительном распределении, на простой плагин для браузера тратится куча памяти. Я считаю, что сборщика мусора Rebol достаточно для обычного использования. (Возможно, в устройстве Android все еще проблемы со скоростью и памятью)

person MaxV    schedule 18.04.2013
comment
Это не имеет ничего общего с современными ПК. (И абсолютно ничего с размером подключаемых модулей браузера.) Как уже объяснил DocKimbel, когда буфер серии заполнен, его необходимо перераспределить, что также может включать копирование всего содержимого существующего буфера серии. Если вы уже знаете, сколько памяти вам понадобится, то без предварительного выделения всегда возникнут накладные расходы на перераспределение, независимо от того, насколько современен ваш ПК. Копирование памяти не бесплатно, поэтому вопрос только в том, когда (а не в том случае) эти накладные расходы также приведут к заметному снижению производительности. - person earl; 18.04.2013
comment
Привет, Макс, спасибо, что ты на StackOverflow — это хорошее место для институциональных знаний, и такие вопросы полезны. Тем не менее, убедитесь, что если вы отвечаете на вопрос, это ответ, а не комментарий! Я проголосовал за ваш другой ответ, чтобы компенсировать чей-то отрицательный голос, но вы должны удалить этот и оставить комментарий. Если вы просто хотите поболтать, присоединяйтесь к нам в комнате Rebol и Red - person HostileFork says dont trust SE; 18.04.2013