Belzebub 0 Опубликовано: 26 декабря, 2021 Хочу мерить tps-ы, не блокируя поток. Все мои попытки тщетны, мб у кого то есть идеи по реализации? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 26 декабря, 2021 10 часов назад, Belzebub сказал: Хочу мерить tps-ы, не блокируя поток. А что именно там блокирует? Обычно же паузу ставят. Вот, вместо паузы делай что-нибудь полезное, а не просто жди. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ECS 1 903 Опубликовано: 26 декабря, 2021 Технически в опенкомпах нет потоков, и все ОСи могут лишь софтверно "скакать" с одной операции на другую, периодически блокируя друг друга и выполняя таски по списку. То есть тут всё блокирующее. Если тебя устроит просто отображать 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 26 декабря, 2021 (изменено) 1 час назад, ECS сказал: event.timer( interval, function() -- Примерное значение TPS рассчитывается как расхождение между желаемым интервалом в 1 сек и фактическим, -- полученным через разницу в датах изменения временного файла local tps = interval / (getRealTimestamp() - lastModified) * 20000 Этот код работает более-менее правильно при условии, если таймер не блокируертся основным кодом. Например, если сразу за кодом таймера запустить os.sleep достаточной продолжительности. Но если вместо os.sleep будет что-то вроде этого for i=1,1e8 do end, то TPS окажется сильно заниженным. Проблему можно решить, если в расчётах использовать не значение interval, а разницу между computer.uptime в моменты запроса getRealTimestamp(). Изменено 26 декабря, 2021 пользователем eu_tomat ошибка: не завышенным, а заниженным 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 26 декабря, 2021 Для иллюстрации предыдущего поста написал короткую демонстрацию: local event = require"event" local uptime = require"computer".uptime local t, t_ local function onTimer() t_ = t t = uptime() print( (t-t_+0.025)//0.05 ) end t = uptime() event.timer( 1, onTimer ) os.sleep( 1.1 ) t = uptime() event.timer( 1, onTimer ) for i=1,2e8 do end os.sleep( 1.1 ) Результаты: 20.0 52.0 Как можно видеть, нет гарантии выполнения события таймера строго в назначенное время. В первом случае таймер сработал строго через 20 тактов. А во втором случае потребовалось 52 такта, хотя предполагалось именно 20. 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ECS 1 903 Опубликовано: 26 декабря, 2021 22 минуты назад, eu_tomat сказал: Проблему можно решить, если в расчётах использовать не значение interval, а разницу между computer.uptime в моменты запроса getRealTimestamp() Согласен, в майносевском примере я так и поступил. Для опеноси хотелось более простой пример привести, мало ли логическая цепь не особо ясна будет 2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
eu_tomat 2 154 Опубликовано: 26 декабря, 2021 2 минуты назад, ECS сказал: в майносевском примере я так и поступил Ой! Пример-то для майноси я пролистал не глядя. Я эту OS даже не запускал ни разу, не то что программы для неё изучать. Штука, конечно, прикольная, но я так и не смог придумать, зачем лично мне нужна MineOS. Прошу понять и простить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ECS 1 903 Опубликовано: 26 декабря, 2021 1 минуту назад, eu_tomat сказал: Штука, конечно, прикольная, но я так и не смог придумать, зачем лично мне нужна MineOS. Прошу понять и простить Хех, да я сам хз, для чего она нужна. Я её как основу гуишную юзаю, чтоб всякие асинхронные мониторилки для реакторов/крафтилен на базе по-быстрому писать, что как раз близко к теме автора. Вообще и на опеноси было норм, но поддерживать постоянные изменения в либах из версии к версии я задолбался, поэтому проще стало написать отдельную ось, чтоб самому удобно было. Прошу понять и простить)0 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Belzebub Автор вопроса 0 Опубликовано: 26 декабря, 2021 6 часов назад, eu_tomat сказал: Проблему можно решить, если в расчётах использовать не значение interval, а разницу между computer.uptime в моменты запроса getRealTimestamp(). Спасибо, вот именно из за отсутствия этой штуки счётчик тпса выдавал неадекватные данные при интеграции в другие программы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
vford 12 Опубликовано: 28 декабря, 2021 (изменено) В 26.12.2021 в 20:40, ECS сказал: Хех, да я сам хз, для чего она нужна Цель существования MineOS сейчас вполне ясна - быть демонстрацией возможностей мода OpenComputers. И она прекрасно с этим справляется. Изменено 29 декабря, 2021 пользователем vford Речевая ошибка 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Хочу мерить tps-ы, не блокируя поток.
Все мои попытки тщетны, мб у кого то есть идеи по реализации?
Поделиться сообщением
Ссылка на сообщение
Поделиться на других сайтах