ECS
-
Публикации
533 -
Зарегистрирован
-
Посещение
-
Победитель дней
203
Сообщения, опубликованные пользователем ECS
-
-
4 часа назад, num_pi сказал:res = res .. string.char(math.random(48, 57))
-
1
-
-
Господни помидоры! 4к строчек для одной проги, УВОЖАЮ
-
1
-
-
1 минуту назад, eu_tomat сказал:Штука, конечно, прикольная, но я так и не смог придумать, зачем лично мне нужна MineOS. Прошу понять и простить
Хех, да я сам хз, для чего она нужна. Я её как основу гуишную юзаю, чтоб всякие асинхронные мониторилки для реакторов/крафтилен на базе по-быстрому писать, что как раз близко к теме автора. Вообще и на опеноси было норм, но поддерживать постоянные изменения в либах из версии к версии я задолбался, поэтому проще стало написать отдельную ось, чтоб самому удобно было. Прошу понять и простить)0
-
1
-
-
22 минуты назад, eu_tomat сказал:Проблему можно решить, если в расчётах использовать не значение interval, а разницу между computer.uptime в моменты запроса getRealTimestamp()
Согласен, в майносевском примере я так и поступил. Для опеноси хотелось более простой пример привести, мало ли логическая цепь не особо ясна будет
-
2
-
-
Технически в опенкомпах нет потоков, и все ОСи могут лишь софтверно "скакать" с одной операции на другую, периодически блокируя друг друга и выполняя таски по списку. То есть тут всё блокирующее. Если тебя устроит просто отображать TPS раз в N сек, то заюзай таймер. Код для опеноси:
local event = require("event") local computer = require("computer") local component = require("component") local gpu = component.gpu -- Возвращает кол-во реальных (не игровых) наносекунд, прошедших с 00:00:00 01.01.1970 до момента изменения файла на диске local function getRealTimestamp() -- Получаем виртуального компонента filesystem, где можно создавать временную помойку local proxy = component.proxy(computer.tmpAddress()) local path = "timestamp.tmp" -- Создаем временный файл proxy.close(proxy.open(path, "wb")) -- Получаем дату изменения local lastModified = proxy.lastModified(path) -- Удаляем его proxy.remove(path) return lastModified end -- Стартуем фоновый таймер, обновляющийся раз в 1 сек local interval = 1 local lastModified = getRealTimestamp() event.timer( interval, function() -- Примерное значение TPS рассчитывается как расхождение между желаемым интервалом в 1 сек и фактическим, -- полученным через разницу в датах изменения временного файла local tps = interval / (getRealTimestamp() - lastModified) * 20000 -- Выводим значение TPS на экран local oldForeground = gpu.getForeground() gpu.setForeground(0xFFFFFF) gpu.set(1, 1, "TPS: " .. math.floor(tps + 0.5)) gpu.setForeground(oldForeground) -- Все операции вывода на экран занимают время, лучше обновить переменную ещё раз для точности lastModified = getRealTimestamp() end )
Профит:
И для майноси:
local computer = require("Computer") local component = require("Component") local GUI = require("GUI") local system = require("System") -- Функция та же local function getRealTimestamp() local proxy = component.proxy(computer.tmpAddress()) local path = "timestamp.tmp" proxy.close(proxy.open(path, "wb")) local lastModified = proxy.lastModified(path) proxy.remove(path) return lastModified end -- Добавляем окошко программы в UI local workspace, window, menu = system.addWindow(GUI.filledWindow(1, 1, 60, 20, 0xE1E1E1)) -- Создаем текстовый виджет по центру окошка local layout = window:addChild(GUI.layout(1, 1, window.width, window.height, 1, 1)) local text = layout:addChild(GUI.text(1, 1, 0x4B4B4B, "Тут будет TPS")) -- Вместо event.timer юзаем computer.uptime local uptime = computer.uptime() -- С файликами история та же local lastModified = getRealTimestamp() local interval = 1 text.eventHandler = function(workspace, text, e1, ...) -- Вычисляем, сколько сек прошло с последнего события local deltaTime = computer.uptime() - uptime -- Если прошло больше ожидаемого интервала if deltaTime > interval then -- Вычисляем TPS local tps = deltaTime / (getRealTimestamp() - lastModified) * 20000 -- Обновляем текстовый виджет text.text = "TPS: " .. math.floor(tps + 0.5) text.width = #text.text workspace:draw() -- Обновляем переменные lastModified = getRealTimestamp() uptime = computer.uptime() end end workspace:draw()
Результат:
-
2
-
-
Еще API компонента не подразумевает буферизации IO-операций, поэтому слишком частые мелкие обращения к компоненту типа fs.write(handle, "1") будут ощутимо медленнее, чем буферизированная обертка из OpenOS. Т.е. если ты прогаешь какой-нибудь EEPROM с сохранением бинарных файлов побайтово, то добавление строкового буфера хотя бы в 1 Кбайт нифигово апнет скорость
-
5
-
-
Если юзаешь одну общую видяху, то можно дописать аргумент gpu.bind(адрес, false), чтобы не сбрасывалось разрешение целевого моника
-
3
-
-
1 час назад, TayzlexBH сказал:Кстати, ос очень прожорливая) приходится делать серверные стойки с 4 планками RAM уровня 3.5.
Отключаешь обои - и вуаля, хватает 2 планок оперативы за глаза, только если не запускать какое-нибудь 3D. Чистая оська в минимальной конфигурации требует ~600 кбайт доступной памяти, и я не сказал бы, что это прям лютые и неадекватные затраты:
Такова цена граф. интерфейса в изначально консольной среде: тут уже хз, как извернуться, чтобы "скукожить" граф. буфер, жрущий минимум 400 кбайт, словно избалованный толстый кис. Остальные 200 кбайт объедков достаются юишным объектам, либам и буферам I/O. В целом опенкомпы по концепции не предназначены для подобных юишных извратов, поэтому смиренно жрем, чо дали
-
3
-
-
1 час назад, eu_tomat сказал:Но если хорошо копать, то что-то недостаточно оптимальное можно найти в любом большом проекте
-
1 час назад, eu_tomat сказал:заняться оптимизацией MineOS.
Ну-ка, ну-ка, какая ее часть тебе кажется недостаточно оптимизированной и почему?
-
2 часа назад, eu_tomat сказал:Какой-либо модификации не подвергался?
Нет, офк. Я ж скинул аналогичный результат на чистом консольном луа той же версии, так чего на разность модов-то грешить? Загвоздка явно в поведении железяк. Но боюсь, я абсолютно некомпетентен в этом вопросе, чтобы сгенерировать какие-либо выводы. Цпуинфа:
8 model name : Intel(R) Xeon(R) Silver 4214R CPU @ 2.40GHz-
1
-
-
7 часов назад, eu_tomat сказал:А объяснение было таким. На обычных операциях (если это не обработка длинных строк или преобразование больших таблиц) наибольший вклад в затраты времени даёт интерпретатор Lua. Вклад же полезной нагрузки минимален. Поэтому простая функция, написанная на Lua, будет исполняться дольше функции из стандартных библиотек. И мой опыт всегда подтверждал эту гипотезу.
Согласен, это так. Но... только в рамках бенчмарка синтаксически различных участков кода на одной машине. Тут, вне сомнений, Lua VM царь и бог, и на результат скорее повлияют локальные особенности трансляции в байт-код, нежели пара лишних операций в исходнике
А как быть в нашем случае, когда эквивалентный код под одной VM на различном железе выдает различную производительность?
-
1
-
-
1 час назад, eu_tomat сказал:Тогда что влияет? Какие предлагаешь варианты?
Железо скорее. Луа-консоль запускал на рабочей вдске, сервак кубача поднимаю там же, т.к. сингловый клиент на дешманском ноуте умирает с TLWY даже на 1млн итераций, не говоря уже о 20 млн. С точки зрения дилетанта могу предположить, что наибольшее влияние на однопоточные вычисления оказывает набор инструкций ЦП, объем кеша и частота. Возможно, надо байт-код для каждого метода и каждой машины чекать, чтобы сказать наверняка (он вообще может отличаться для одинаковых версий луа?)
-
1
-
-
1 минуту назад, eu_tomat сказал:Что-то не бьются у нас результаты. Какая у тебя версия OpenComputers?
OpenComputers-MC1.12.2-1.7.5.192.jar
-
1
-
-
6 минут назад, eu_tomat сказал:Что-то у тебя интервал времени получился крошечный. Там погрешность получается большая
Интервал зависит от кол-ва итераций, а оно такое же, как в примере Zer0Galaxy. Тестил я на десктопном некомпилируемом Lua 5.3.1, лень кубач было ставить. Не нравится? Да пожалуйста, вон результат на 2e7 итераций:
Constant 1.152 Upvalue 1.375 math.floor 1.749 floor (no indexing) 1.425 Lua 5.3+: num + 0.5 // 1 1.524 Lua 5.2+: num - num % 1 1.733И на опенкомпах:
Один фиг победа за первым методом
-
1
-
-
4 часа назад, Zer0Galaxy сказал:Опыт подтверждает твои выводы:
4 часа назад, eu_tomat сказал:не хуже должен быть вариант с использованием local floor=math.floor
Чекнул дополнительно пару известных вариантов округления. Топикстартеру респект за наиболее производительное решение:
Constant 0.017 Upvalue 0.023 math.floor 0.027 floor (no indexing) 0.025 Lua 5.3+: (num + 0.5) // 1 0.022 Lua 5.2+: num - num % 1 0.026
-
1
-
1
-
1
-
-
Только что, OpenReactor сказал:Сервер то не мой. Ладно тогда время кастылей)
Дык попробуй отослать MOTD\r\n или MOTD\n, в 90% случаев серваки должны адекватно проинтерпретировать сообщение, если это прям не лютый кастом
-
1
-
-
В 20.08.2021 в 22:12, OpenReactor сказал:Осталось найти решение
Сокет-сервак в режиме ресивера работает по накопительному принципу, и сообщения крайне часто будут стоять в буфере друг за дружкой, ожидая обработки, эт нормально. Высокоуровневые библиотеки решают эту проблему через протоколы прикладного уровня по OSI, а ты работаешь с "чистым" сокетом, поэтому придётся минимально пораскинуть мозгами
Решений несколько: можно на клиенте перед отсылкой пакета добавлять в начало байт-префикс с длиной содержимого, а на сервере читать накопившийся результат, основываясь на принятых длинах пакетов. Если этот вариант слишком сложен или избыточен (например, если твой софт передает преимущественно короткие сообщения-команды), то можно попросту разделять пакеты любым спец. символом - обычно в сокет-чатах используют символ перевода строки \n
-
1
-
-
19 минут назад, ProgramCrafter сказал:Если кому-то понадобится ФС, поддерживающая кучу файлов, для кассет - можете меня тыкать, у меня осталось немного доработать
)))
https://computercraft.ru/topic/4340-tapfat-faylovaya-sistema-dlya-kasset/?tab=comments#comment-49345
-
1
-
-
В 17.08.2021 в 03:36, whiskas сказал:да дерево это понятно что круто. Но я думаю легче будет сделать хеш таблицу
Даже в случае с хеш-таблицей держать все индексы БД в памяти - такая себе затея, т.к. оператива не резиновая, а скрафтить RAID на 12 мбайт не составит особого труда. Основной проблемой при работе с индексами, хранящимися на диске, у тебя будет скорость чтения и реиндексации при записи, т.к. опенкомповские диски прям сильно лимитированы по I/O операциям. Даже если прикрутить к хеш-таблице бинарный поиск, то это слабо поможет жирным БД, исчисляемых мегабайтами, т.к. глубина рекурсии при поиске может достигать нескольких тысяч. К сожалению, чем жирнее БД, тем более заковыристый алгоритм требуется для ее поддержки, и заюзать древовидную структуру для хранения индексов будет оптимально, т.к. для чтения с диска нужно минимизировать число узлов, которые обходит поисковая система. Ну а про удаление/вставку со сдвигом индексов и говорить нечего
-
2
-
-
1 час назад, eu_tomat сказал:О какой библиотеке идёт речь? Стандартная библиотека в составе OpenOS не может корректно работать с таким кодом.
Это особо и не важно, т.к. отсылающий код взят у топикстартера, а запись в сокет, судя по всему, у него работает. Либо это кастомная интернет-либа, либо код выложен не полностью, пофигу. Главное - дать наводку на листенер internet_ready
-
1
-
-
14 часа назад, OpenReactor сказал:Я хочу допустим запросить motd ещё раз то я получу nill
soc:write("MOTD")
motd = soc:read(100)
Сокет-сервак работает параллельно с твоим клиентом, пишущим MOTD и ждущим ответа. Клиентские данные могли не успеть обработаться серваком во второй раз, могли проинтерпретироваться в виде сдублированной строки "MOTDMOTD", а могли и вовсе быть поглощены ZOGом во имя вселенского благополучия. Ты же делаешь :read() в слепой надежде на успех. Непорядок! Подписывайся на ивент internet_ready, делай небольшую задержку между отправкой запросов на MOTD, разбивай сообщения через символ переноса строки, правильно обрабатывай их на сервере, а затем уже читай данные:
local soc = require("internet") local event = require("event") event.listen("internet_ready", function() local motd = soc:read(100) ... end) soc.open("localhost", 2888) soc:write("MOTD\r\n") os.sleep(1) soc:write("MOTD\r\n") os.sleep(1) ...
Либо, если оч сложна, юзай костыль со слипом. Но тут тоже никаких гарантий, то данные пришли и обработались корректно:
local soc = require("internet") soc.open("localhost", 2888) soc:write("MOTD") os.sleep(1) motd = soc:read(100) soc:write("MOTD") os.sleep(1) motd = soc:read(100) ...
-
1
-
-
Оптимизированы наиболее часто используемые методы библиотеки Screen, работающей с экранными буферами: если ранее для каждого рисуемого пикселя выполнялась проверка вхождение в регион отрисовки, то теперь все прямоугольные команды автоматически рекомпонуются, чтобы уместиться в этот регион. Странно, что это не было сделано изначально, но тем не менее скорость перемещения сложных оконных приложений с кучей мелких прямоугольников и картинок (типа местного Finder) ощутимо подросла
Ну и забавы ради добавлен метод screen.blur(), применяющий эффект размытия к указанному региону и, опционально, накладывающий цветовой фильтр, а также виджет GUI.blurredPanel, чтобы создавать окна с заливкой в стиле AcrylicBrush из UWP
Вообще изначально было реализовано полноценное размытие по Гауссу, но, учитывая мизерные размеры экранов, оказалось, что простого box blur будет более чем достаточно, и визуальной разницы нет. Вопрос прожорливости остается за кадром:
-
3
-
1
-
-
Callback-функции типа onTouch/onResize существуют только для отдельно взятых элементов, а не для каждого GUI.object. Поэтому проще всего "заоверрайдить" метод :close() для закрытия окна, как это сделано в приложениях типа 3D Print. По итогу что в случае callback-функций нужно создавать лишнюю функцию, что в случае "оверрайда", поэтому тут дилемма скорее эстетического характера
local baseWindowClose = window.close window.close = function(...) -- Профит baseWindowClose(...) end
-
2
-

Как получить случайное целое число?
в Lua
Опубликовано:
Оставлю свои пять копеек для тех, кому нужно генерировать рандомные числа фиксированной длины. Хотя к теме это относится опосредованно, но мало ли:
Вместо math.floor для ускорения процесса можно использовать операцию целочисленного деления // 1.0, однако она сохраняет нулевую дробную часть в результате и доступна только в Lua 5.3. На ваше усмотрение, короче. Результат: