eu_tomat
-
Публикации
2 666 -
Зарегистрирован
-
Посещение
-
Победитель дней
331
Сообщения, опубликованные пользователем eu_tomat
-
-
Затравочный пост о лагомерках и лагодромах
Выполняя обещание, данное в других темах, привожу список известных мне лагомерок без их подробного анализа:
- os.clock() растёт быстрее при нехватке вычислительных ресурсов сервера. Предоставляет единственно верный способ оценить шансы приближения TLWY. Но значения os.clock() относительны и зависят от множества факторов.
- computer.pullSignal(0) в норме выполняется около 4 раз за тик, но во время лагов количество вызовов за тик уменьшается. Вносит минимальный вклад в лаги сервера, т. к. почти всё время тратится на сон. Оно ненулевое, как может показаться.
- Оценка соотношения роста computer.uptime() и реального времени сервера позволяет вычислить значение TPS. Но падение TPS в чанке не всегда указывает на лаги сервера, так могут проявлять себя штатные механики Майнкрафта и модов.
- Обращения к периферии в норме требуют для своего выполнения одного тика. Время, затраченное сверх одного тика, сигнализирует о лагах сервера и о возможном устаревании данных, полученных компами от периферии.
Во всех лагомерках заложено фундаментальное противоречие. Информацию о лагах требуется получать оперативно, в реальном времени, каждый тик. Но интенсивно работающая лагомерка вносит собственный вклад в лаги сервера. По этой причине я призываю отказаться от интенсивных замеров лагов на игровых серверах. Например, если критичный к лагам код планируется выполнить через минуту, то почти всё это время имеет смысл потратить на сон, а интенсивность измерений наращивать по мере приближения к критическому моменту. Нет смысла измерять то, что утратит свою актуальность к моменту использования.
Кроме того, любой интенсивно работающий код имеет ненулевой шанс аварийно завершиться с ошибкой too long without yielding. Этой ошибки на 100% может избежать лишь код, 100% времени проводящий в ожидании. Во всех остальных случаях возникновение TLWY определяется лишь вероятностью. Поэтому, скрипт должен дольше спать и меньше работать. Чем больший вклад вносит скрипт в лаги сервера, тем с большей вероятностью он аварийно завершится по TLWY.
Оборачивание кода в pcall не даёт 100% гарантии избежать аварийного завершения по TLWY. Шансы зависят не только от интенсивности вычислений в самом коде, но и от перегруженности сервера. На стабильном сервере pcall почти всегда спасает код от завершения по TLWY. Но на сильно лагающем сервере pcall почти всегда не успевает.
В этом посте я не раскрыл всех деталей использования перечисленных способов обнаружения лагов. Также, возможно, я забыл упомянуть другие достойные способы или даже не знал их. Поэтому задавайте вопросы, предлагайте свои решения, проводите собственные исследования, не дожидаясь моих. По результатам обсуждения я попробую собрать подробный гайд о лагомерках и лагодромах.
-
2
-
В эту тему я планирую выкладывать разрозненные фрагменты знаний о времени в Майнкрафте.
Здесь можно обсудить всё, что связано с ходом времени в Майнкрафте:
- какое время считать достоверным
- как одни виды времени соотносятся с другими
- какую информацию можно получить, детектируя возникающие артефакты течения времени
- как оценить лаги на сервере или лаги, вносимые своим кодом
- как сделать свой код устойчивым к лагам сервера.
-
2
-
4 часа назад, hohserg сказал:TPS можно измерить просто сравнив задержку os.sleep(n) с изменением реального времени, взятого где-нить из инета
Измерение TPS сервера, ориентируясь на время из интернета является, пожалуй, одним из худших вариантов. Пакеты через интернет доходят с очень труднопрогнозируемым лагом. Реализация подобия NTP это отдельная задача. Для измерения небольших интервалов времени более предпочтительным выглядит получение времени через модификацию файла. Время же из интернета обычно требуется для оценки запаздывания или опережения времени на сервере, что для нашей задачи совершенно некритично.
Но и оценка TPS относительно времени модификации файла тоже имеет свои ограничения. Я, пожалуй, напишу отдельный пост обо всех найденных мной лагомерках. У каждой есть свои достоинства и недостатки.
-
2
-
1
-
-
5 минут назад, ProgramCrafter сказал:с проблемой TLWY может справиться что-то вроде pcall
Не всегда. Даже если сразу после pcall выполнить computer.pullSignal, есть шанс, что уступка времени не успеет произойти до аварийного останова компьютера. Хоть десятикратным слоем pcall можно обернуть, это не всегда помогает.
9 минут назад, ProgramCrafter сказал:Компьютер можно запитать от таймера.
Да, в конечном итоге так и делаю. Либо таймер, либо дополнительный контроллер, выполняющий функцию таймера. Но в конечном итоге и дополнительный таймер и контроллер вносят свой вклад в снижение TPS, об этом тоже следует помнить. Кроме того, задержка между выключением и пробуждением управляющего компьютера должна быть минимальной, т.к. хороший микроконтроль должен обеспечивать манипуляции с реактором в точно отведённые для этого интервалы времени. Поэтому использование дополнительного микроконтроллера мне кажется более компактным и гибким способом.
18 минут назад, ProgramCrafter сказал:Возможно, чтобы измерить лаги, стоит держать корпус реактора в нагретом состоянии, а в выключенный реактор класть теплоотвод? Тогда компьютер сможет проверить, в какой момент изменилась температура реактора и насколько низок TPS.
За это время, пока я не был активен в этой теме, я нашёл более простой способ оценки лагов даже на выключенном сервере: измерять время, затраченное на чтение состояния реактора или его слотов. В норме на это требуется один тик, при микролагах изредка требуется два тика. А при огромных лагах у меня уходило даже 36 тиков. Я упоминал об этом эксперименте в теме с заказом "Очень много электричества".
-
В девяностые годы в России был популярен анекдот. В нём один бизнесмен предлагает другому купить вагон сахара. Второй соглашается приобрести за миллион. После заключения сделки один из них уходит искать вагон сахара, а другой пытается достать миллион.
3 часа назад, yura0138 сказал:эта тема и создавалась для решения ограничения в 1 реактор
Я не заметил в описании задачи ограничения в 1 реактор, но пусть будет один. Тогда проясним и другие ограничения. Сколько овец разрешено использовать при обслуживании реактора?
-
3 минуты назад, yura0138 сказал:тогда нужна еще прога для стрижки овец, или искать ещё способы добыть лазурит
Эта схема имеет два достоинства: большой выход энергии с одного реактора и хорошую эффективность использования топлива. А главным недостатком схемы является высокий расход лазурита или редстоуна. Это проговаривалось в начале темы.
Если схема в определённых условиях начинает порождать проблемы вместо того, чтобы их решать, то что мешает заменить её на более подходящую? Например, вместо одного реактора на конденсаторах можно использовать несколько реакторов на теплоотводах, которые не требуют дополнительных расходных материалов.
-
1
-
-
46 минут назад, Doob сказал:@yura0138 реактор может выдать максимум 8192 EU/t.
Это, наверное, зависит от комбинаций модов и настроек. Я сейчас проверил ограничение выхода энергии. Схему выкладывал не самую лучшую и реактор грел не до максимума. Получил выход энергии 4200 eu/t на уране и 20237 на MOX. MFSU за секунду работы набрал 404753 eu, что полностью соответствует выходу 20237 eu/t.
Получается, что ограничение в 8192 eu/t проявляет себя не всегда.-
1
-
-
18 минут назад, ProgramCrafter сказал:стабильные схемы будут проигрывать схемам, использующим микроконтроль со стороны робота. Пример такой схемы от @eu_tomat (https://computercraft.ru/topic/2822-mikrokontrol-yadernyh-reaktorov-ic2exp/?do=findComment&comment=39656):
Даже в самых смелых фантазиях я не планировал осуществлять микроконтоль этой схемы роботом. В отличие от транспозера робот в большинстве случаев просто не успеет обменять компоненты в интервале между реакторными тиками. Реактор от этого не взорвётся, но немного снизит среднюю производительность.
Кроме того, я бы не стал поручать роботу какие-то дополнительные задачи кроме обслуживания реактора. Схемы, требующие микроконтроля, обязывают постоянно держать руку на пульсе. Как минимум, требуется отслеживать лаги сервера и не отключаться по TLWY.
Для увеличения производительности я рекомендую рассмотреть метастабильные схемы на MOX. Им требуется микроконтроль лишь на этапе разогрева и во время замены отработанных стержней. Реакторы с такими схемами можно смело оставлять без присмотра. Содержащиеся в них компоненты не перегорают, а сами реакторы не взрываются.
-
1 час назад, hohserg сказал:Тут недалеко темка была, показывающая, что одна эта задача целого конкурса стоит
Сложность задачи напрямую зависит от используемой схемы и режимов работы реактора. А требования использовать экстремальные варианты в этой теме не было. Обычный реактор на уране с генерацией 420 eu/t не взрывается из-за лагов, и какого-то сложного управления не требует.
-
2
-
1
-
-
13 часа назад, Taruu сказал:Исправил код вроде теперь все правильно...
Не совсем. Так файл не закроется. Вот API для компонента Filesystem. Можно закрывать, например, таким кодом:
fs.close(fs.open("/time", "w"))
-
1 час назад, hohserg сказал:А что, если юзать несколько компов каждый со своим телепозером, чтобы каждый работал только с частью слотов(или даже с одним)?
Зависит о цели.
Если требуется опросить большее количество слотов за единицу времени на стабильном сервере, то несколько компов помогут решить эту задачу. Но лучше было бы научиться обходиться опросом меньшего количества слотов.
Если мы говорим о ситуации с лагающим сервером, то несколько компов, пытающихся дублировать работу друг друга, способны лишь ухудшить результат. Сервер же не просто так лагает, ему недостаточно физических ресурсов. И новый виртуальный комп не добавит этих ресурсов, а наоборот, потребует дополнительных.
-
1
-
-
12 часа назад, Taruu сказал:Смотря на то как он обновляет экраны он ели ели успевает в секунду.
В программе присутствует ошибка. Из-за неё 96% попыток обновлений времени являются холостыми, и поэтому фактические обновления происходят со средней частотой примерно 4 раза в секунду. При этом интервалы обновления неравномерны, они заданы случайными факторами.
15 часов назад, Taruu сказал:local function getRealTime() local handle = fs.open("/time", "w") local timestamp = fs.lastModified("/time") / 1000 + t_correction return os.date("%H:%M:%S %d.%m.%Y", timestamp) end
Если не закрывать открытый файл, то последующие попытки его открытия будут безуспешными до тех пор, пока файл не будет закрыт сборщиком мусора.
Закрытие файла + задержка между обновлениями в 1/4 секунды дадут гораздо более приятный глазу эффект. И нагрузка на сервер снизится раз в 30.
-
14 часа назад, NEO сказал:Видимо следствие того что потоки для компов низкоприоритетные.
Да, подтвердилась гипотеза о лагах при получении ответа от периферии. Я провёл эксперимент, имитируя сильные и продолжительные лаги. Оказалось, что вызов transposer.getStackInSlot() может иногда длиться до 36 тиков. И это, я думаю, не предел. Реактор за время между двумя последовательными чтениями состояния одного слота иногда успевал отработать три своих такта.
Выводы:
- Алгоритм микроконтроля должен быть по возможности экономным. Любое лишнее действие сужает пространство до манёвра. Иногда будет отсутствовать не только возможность успеть выключить реактор, но и даже зарегистрировать момент перед взрывом.
- Даже самый лучший алгоритм микроконтроля может не спасти реактор во время сильных лагов. Риск можно минимизировать, отключая реактор при обнаружении лагов, но шанс не успеть всё равно сохранится.
Впрочем, не всё так плохо. Если принять все необходимые меры, то шансы на взрыв не велики. А риск может быть оправдан возможностью обойти ограничение на количество реакторов в привате. Для отдельного реактора риск можно было бы снизить, чуть чаще заменяя конденсаторы, например, не за секунду, а за несколько секунд до критического износа, но это палка о двух концах: чем чаще выполняются какие-либо манипуляции со стороны OpenComputers, тем сильнее будут лаги в других компах. Поэтому по возможности следует стремиться не повышать, а снижать частоту любых действий.
-
3 минуты назад, Taruu сказал:C тактированием компов. И обновления их элементов.
Стандартная частота обновления объектов в Майнкрафте составляет 20 тиков в секунду. А про бюджеты вызовов недавно писал @Fingercomp в своём блоге: Прямые и кривые методы компонентов.
-
1
-
-
1 минуту назад, Taruu сказал:Можно мне умный текст где все эти механики описаны?
Какие именно механики?
-
16 минут назад, Taruu сказал:Смотря на то как он обновляет экраны он ели ели успевает в секунду.
Без задержки эти часы будут пытаться обновить показания с частотой около 120 раз в секунду. А сервер сможет обновить картинку на мониторе с частотой не более 20 раз в секунду. Значит, добавив задержку всего в один тик, можно без заметного ухудшения снизить нагрузку на сервер в 6 раз. Да и 20 раз в секунду нет особого смысла обновлять часы. Уже при частоте около 4 раз в секунду обновление перестаёт играть заметную роль.
-
-
11 минуту назад, hohserg сказал:Реактор работает независимо от тиков?
Это вряд ли. Скорее всего, в полном соответствии с тиками. Я могу ошибаться, но склоняюсь к тому, что лагает исполнение кода Lua в OpenComputers. Причём, слово "лагает" я использую в изначальном его смысле, когда ожидаемое событие приходит с задержкой. Боюсь сейчас соврать, результатов экспериментов под рукой нет, но, насколько я помню, обращение к периферии вместо одного тика иногда требует двух тиков, а в моменты сильного снижения TPS задержка доходила и до 5 тиков. И это, возможно, не предел.
21 минуту назад, hohserg сказал:А реактор вообще детерминированно работает? И без псевдорандома?
Все мои эксперименты подтверждали абсолютно детерминированную работу реакторов. Случайности возникают вокруг реактора: случайным образом поджигаются блоки или превращаются в лаву. Блоки обшивки ЖЯР тоже могут выгореть случайным образом. Но компоненты реактора взаимодействуют друг с другом абсолютно предсказуемым образом.
24 минуты назад, hohserg сказал:Если совместить такой подход с независимой от тиков реализацией os.sleep, то это должно дать хороший результат
Я плохо понял о чём здесь идёт речь. Чем плоха реализация os.sleep, если не вешать на него тяжёлые обработчики событий? Работа os.sleep основана на вызовах computer.pullSignal, другого вменяемого способа для создания задержек нет.
Чтобы понять, насколько хорошим будет результат при фиксированных задержках, нужен ряд экспериментов и правильно интерпретация их результатов:
- Надо всё-таки понять, в каком месте возникает джиттер: на этапе тиков реактора, или на этапе получения ответа от транспозера.
- Надо как-то определить теоретически максимально возможный размер джиттера.
- Надо проверить, нет ли дрейфа циклов ректора при выгрузке-загрузке чанков.
Пока ответы на эти вопросы не получены, приходится подстраховывать частой проверкой состояния какого-либо из слотов реактора. Необязательно выполнять проверку каждый тик. Время замены очередного отражателя известно с точностью до секунды. Поэтому уменьшаем это время на одну секунду и смело спим. А потом начинаем каждый тик проверять точный момент критического износа отражателя. Как только поймали момент, заменяем отражатель.
-
1
-
8 часов назад, hohserg сказал:А за сколько примерно можно чекнуть 13 слотов со старым апи? Если это не слишком большая задержка, то можно просто офать реактор до проверки и врубать после проверки и замены конденсаторов.
13*0.05 = 0.65 секунд на проверку. Плюс 2*0.05 = 0.1 секунд на замену одного отражателя. Вполне реально. Но при сильном снижении TPS сервера можно и не успеть произвести замену. Особенно, если требуется заменить более одного отражателя за раз.
Есть более быстрый способ контроля, но он потребует усложнения алгоритма. Реактор не является чёрным ящиком, и его текущее состояние поддаётся вычислению из предыдущих. В большинстве случаев даже не требуется писать эмулятор реактора. Достаточно вычислять лишь ключевые значения. Что для этого нужно знать?
Во-первых, компьютеры OpenComputers определяют время с точностью до тика. Реакторы и все его компоненты одномоментно изменяют своё состояние один раз в 20 тиков. Во время лагов интервалы между реакторными тиками могут становиться неравномерными, сжимаясь и расширяясь на несколько майнкрафтовских тиков. Но в одном можно быть уверенным: если в какой-то момент была зарегистрирована смена состояния одного из компонентов реактора, то изменилось и состояние других компонентов, если схема вообще предполагает изменение их состояния.
Во-вторых, некоторые из малых изменений состояний реакторных компонентов невозможно остследить по причине слегка кривой арифметики. Поэтому очередной реакторный тик не всегда удаётся отследить посредством проверки, например, прочности MOX-сборки, и тем более, урановой сборки. Но в нашей схеме отражатели сгорают быстро, их прочность меняется каждый реакторный тик на очень большие величины, которые невозможно скрыть даже имеющейся арифметикой.
В-третьих, в зависимости от применённой схемы можно посчитать точное время работы любого из компонентов реактора. Это позволяет заранее составить график плановой замены компонентов. Для максимальной защиты реактора от лагов сервера график замены компонентов должен быть по возможности равномерным.
Знание этих механик позволяет вычислять состояние всех компонентов реактора, ориентируясь по состоянию лишь одного из них, экономить драгоценные тики и повышать устойчивость микроконтроля. А пр аккуратном программировании можно даже снизить нагрузку на сервер.
-
2
-
-
14 минуты назад, NEO сказал:Вызывать каждую итерацию pullSignal - нерационально. Думаю стоит уточнить. Ибо драгоценное время тратится впустую на блокирующую операцию.
Категоричное утверждение. Рационально будет или нет, всецело зависит от используемого алгоритма и размера отдельной итерации. А в теме эти параметры никак не обозначены.
-
4 минуты назад, Avevad сказал:Так, а сигнал случайно мы не вытащим? Просто нужно, чтобы во время выполнения этой части такого не произошло (хотя может и пофиг на самом-то деле). И еще - почему все-таки не работает yield?
Сигнал случайно вытащить можем. Поэтому, если важно не терять сигналы, то потребуется написать обработчик. Если пропуск сигналов критичен, то проверка сигналов обязательна в любом случае, т.к. очередь сигналов ограничена и может быть переполнена.
yield, скорее всего, нужно вызвать с параметром времени ожидания yield(0), или же ждать сигнала. Как в этом случае обрабатывать само событие, я не знаю, не пробовал.
-
1
-
-
Выполнение computer.pullSignal(0) обеспечит минимальную уступку времени.
-
1
-
-
50 минут назад, ProgramCrafter сказал:Немного допилил стандартный tape.lua, чтобы он мог считывать файл с кассеты: pastebin get pTVnhYwp /usr/bin/tape.lua
Замечание: в исходном файле не должно быть нулевых байт.
Интересное дополнение, хотя и спорное.
Во-первых, проще было бы не втискиваться в рамки стандартной утилиты, а написать свою, специально предназначенную для записи на ленту и чтения с неё файлов с произвольными данными. И ориентироваться не по нулевому байту, а по размеру файла, заданному в заголовке.
Во-вторых, непонятна применимость подобного подхода. Обычные жёсткие диски по причине их малого объёма не позволяют задействовать весь потенциал ленты. Думаю, полезной была бы архивная файловая система с ограниченными функциями: произвольное чтение любого из уже записанных на ленту файлов и дописывание в конец ленты новых файлов.
-
2
-
-
@norecord Сканирование столбцами было единственным вариантом в ранних версиях OpenComputers. Но позже появилась возможность сканирования произвольной области общим объёмом не более 64 блоков. Это позволяет ускорить сканирование плоской местности в 64 раза.
Сейчас программа выполняет 1089 сканирований за 55 секунд, хотя достаточно лишь 18 сканирований и 1 секунды. Правда, потребуется усложнить код.

Фармер иридия Нью-Байт
в Конкурсы
Опубликовано:
Про лагомерки и лагодромы ответил здесь