ECS
-
Публикации
533 -
Зарегистрирован
-
Посещение
-
Победитель дней
203
Комментарии блога, опубликованные пользователем ECS
-
-
4 часа назад, Fingercomp сказал:unicode.sub и computer.uptime — это не методы компонентов, а функции, которые практически напрямую дёргают методы луа и потому несравнимо дешевле
Я и не утверждал обратного, это уже какая-то нездоровая полемика. Проясню:
1) Я продемонстрировал, что комп умирает на несколько сек при обращении к gpu.get, предположив, что обращение к ненулевому буферу ни разу не бесплатное
2) Ты сообщил, что доминирует некий оверхед, а расход бюджета при обращении к ненулевому буферу должен быть 2-31
3) Я ответил, что значение в 2-31 слишком мало, и бюджета после 16к вызовов должно оставаться с запасом, и проблема явно в другом месте
4) Ты пояснил, что имел в виду под оверхедом, упомянув нативные либы, интерфейс Lua <> Scala и сам бюджет вызовов
5) Я не согласился, приведя пример с 16к вызовами unicode и computer, имитирующими оверхед без расхода бюджета, и работающий незаметно с точки зрения производительности. Поскольку из примера был исключен лишь расход бюджета, а работа нативных либ и прокидывания данных через Lua <> Scala сохранены, я сделал вывод, что к тормозам приводит именно бюджет
5 часов назад, Fingercomp сказал:Потребление бюджета вызовов при этом остаётся околонулевое
Разве это не подтверждает тезис о том, что gpu.get кушает сильно больше 2-31 бюджета? Может быть, каждый вызов прямого метода компонента расходует некое константное кол-во бюджета в дополнение к прописанному в @Callback значению?
-
1
-
-
22 минуты назад, Fingercomp сказал:Именно про этот оверхед я и говорил. Я предполагаю, что софтверное склеивание тормозит из-за него
Я тоже как раз про него и говорил. И по-прежнему не соглашусь. Заменяешь тело функции throttle из примера выше на любой код уровня Lua ↔ Scala типа unicode.sub("abcdef", 1, 2) или computer.uptime(), вызываешь его 160 * 50 * 2 раз перед выводом графики на экран через bitblt - и ничего не изменится. С позиции наблюдателя никаких микро-задержек не будет, bitblt отработает так же, как и без искусственного замедления, потому что, как ты сам подметил, bitblt скушает в сотни (если не тысячи) раз больше бюджета. А теперь вставляем 16к вызовов gpu.get на ненулевой буфер и наслаждаемся мертвым компом. Поэтому смею предположить, что реальный бюджет обращения GPU к ненулевому буферу сильно значимее 2-32, и практический эксперимент это подтверждает
51 минуту назад, Fingercomp сказал:P. S. В довольно древней версии оцелота есть гпу-буферы в том виде, в каком они оказались в OC 1.7.6, и график бюджета вызовов. Можно протестить прогу там.
Чекнул, ловлю рантаймовую оплеуху. В кубаче работает, так что фиг с ним
-
1
-
-
1 час назад, Fingercomp сказал:Возможно, не бюджет расходуется дико (насколько я понял, каждый прямой вызов в побочный буфер потребляет 2-31 единиц бюджета)
Разве это не смехотворно малая величина? В таком случае от бюджета серверной стойки в полной комплектации в 1.4 единицы должно оставаться 1.4 - 160 pix * 50 pix * (2 setActiveBuffer + 2 get) * 2-31, то есть 1.3999850988387
Хорошо, предположим, остаток полностью съедают вызовы функций. Пишем для теста любую функцию-заглушку и вызываем её примерно такое же кол-во раз, что и при группировке схожих пикселей:
local function throttle() local a = 123 local b = a + 456 local c = a + b ^ a end function screen.update() for i = 1, 160 * 50 * (2 + 2) do throttle() end componentInvoke(GPUAddress, "bitblc", 0) end
И... оно работает с той же скоростью, что и в первом примере. То есть на глаз разница не видна, хотя технически она, конечно, есть. Поэтому, имхо, расход бюджета сильно-сильно больше, а хук на вызовы особой роли не играет. Жаль только, что нет фичи вывода значения бюджета через debug.getCallBudgetValue, чтобы знать наверняка
1 час назад, Fingercomp сказал:Кроме того, там можно выделять не два буфера по 160×50, а один на 160×100, например: число вызовов setActiveBuffer вдвое станет меньше
Хорошая идея. Закодил, чекнул, скорость действительно чуть возросла, но осталась в пределах ~1 кадра в 3 сек. Вообще мы осознанно убрали bitblc в угоду самописному решению, которое явно проигрывает, так что копать дальше в этом направлении смысла мало. Плюс у нас происходит дублирование вызовов setBackground/setForeground: первый раз во время отрисовки основной графики в буфер, а затем второй раз, но уже в сгруппированном по цветам виде при выводе на экран. Бедная видяшечка, на тайваньских майнинг-фермах и то живется легче (9
-
1
-
-
6 часов назад, Fingercomp сказал:К слову, насколько сильно будет тормозить решение, которое перенесёт массивы-буферы из луа в vram, но склеивание операций и рендер будет проводить всё так же в луа, не используя bitblt?
Идея занятная, но тормозит люто. Подправил либу, после склейки дело дошло до рендеринга лишь спустя ~5 сек, то есть комп фактически виснет на процессе поиска пикселей со схожими цветами на тоннах вызовов setActiveBuffer/get. У меня вообще зародилось смутное подозрение, что все операции над буферами ни разу не zero cost даже с поправкой на искусственный троттлинг хука вызовов в machine.lua. И ладно бы вывод на экран - сам процесс рисования в буфер через setBackground/setForeground/set явно кушает бюджет. Как говорится, численно доказать не могу, но эмпирически чувствую
-
1
-
1
-
-
Для теста видеобуферов набросал максимально упрощенный рендерер для майноськи. Без поддержки изображений, прозрачности и транзиций - оставил лишь суровые прямоугольники и цветной текст:
Плюсы: расход RAM упал до 25% на полностью инициализированную систему с загруженными (но не отрисованными) иконками. Для слабых машин это очень хороший показатель, и освободившиеся ресурсы можно было бы направить на прикладной многозадачный софт.
Минусы: оно лагает сильнее, чем софтверное решение с графоном!11
Но, будем честны, я натягиваю сову на глобус. Концептуально фича крайне сочная, API удобное и не ломает старые проекты, написанные под прямую работу с GPU. Думаю, она будет идеальным решением для узкозадачных юишных софтин типа мониторилок реакторов, кнопочных контроллеров для умного дома, текстовых чатов или рисовалок - иными словами, для всего, что могло слегка подлагивать из-за прямой отрисовки. И если раньше надо было извращаться с порядком операций, экономя каждый тик, то теперь можно кодить гораздо комфортнее. Хотя мне все равно чуточку обидно. Но лишь чуточку.
-
4
-
1
-
-
В 16.06.2021 в 16:23, Fingercomp сказал:Но с задержкой в 50 ms адекватно играть на пианинке (ну, лично мне) невозможно.
Угу, согласен. Изначально так и сделал - но толково работать педальками и играть с комфортом не вышло. Пробовал также экспериментировать с разбиением ноты по тикам, составляя её из "кусочков" и множества вызовов .process: в этом случае приходится имитировать ADSR-огибающую вместо штатной и смириться с артефактами на "стыках" одной ноты, проявляющиеся даже в локалке, не говоря уже о внешнем серваке
В 16.06.2021 в 16:23, Fingercomp сказал:Если сделать интерфейс вроде трекера, то можно посылать на звуковую карточку уже готовые аудиокуски, а с миди-клавиатуры ввод принимать, чтобы сориентироваться, какую ноту дальше написать или понять, норм аккорд подобрал или не очень
Вообще заманчивая идея. Насколько помню, кроме твоего Synth никто не озаботился реализацией DAW в кубаче, всё через внешний софт. В целом да, тут проблем с вводом не возникнет, т.к. сам ввод не столь приоритетен, как конечный результат. А вот бесшовно воспроизвести сложный трек с ограничением в 8 каналов будет всё так же проблематично
В любом случае спасибо за уточнение. Видимо, придётся делать комбинированный вариант с опциональным подключением нескольких карт с каким-нибудь хитрым алгоритмом распределения задач
-
@Fingercomp На днях перечитал сей замечательный гайд, и захотелось ретранслировать по TCP сигналы с MIDI-клавы прямо в кубач, т.к. звуковая плата в теории подходит для игры монотонных мелодий типа "кузнечика". Система вроде простая, но либо я дурак, либо плата не позволяет асинхронно воспроизводить новые звуки до тех пор, пока предыдущий sound.process() не завершён. То есть бесполезно пытаться ставить в очередь новые инструкции типа sound.setFrequency(), sound.delay() на любом из 8 каналов, т.к. они будут игнорироваться вплоть до завершения предыдущих инструкций.
Вопрос: а чо делать-то? Есть ли какой-то легальный способ воспроизвести ноту длительностью в 500 мс, а затем ещё одну, но с задержкой в 100 мс после начала предыдущей, позволяя играть на инструменте в реальном времени? В голову приходит только установка нескольких звуковых плат, но это звучит костыльновато. Для чего тогда нужна система 8 каналов, если sound.process() ждёт завершения очереди инструкций на каждом из них? Только для воспроизведения заранее известной последовательности нот?
-
1
-
1
-
-
10 минут назад, Fingercomp сказал:С другой стороны, если ему надо что-то закостылять, чего автор либы не предусмотрел, есть где развернуться.
Эх, вот бы сюда сочный protected для подклассов... И костыляешь что хочешь, и либа целёхонькая
-
1
-
1
-
-
32 минуты назад, Fingercomp сказал:Не, do .. end — это исключительно для структурирования кода конструкция
Я не про do ... end, а про __. Дело привычки, видимо. Крайне сложно принять факт наличия публичных полей, которые "эстетически" помечены приватными в ООП-системе. Я бы их тогда в сам объект вовсе не вносил, оставляя реализацию в виде локальных функций в начале скрипта. Впрочем, либа твоя, хозяин-барин, мяу
-
1
-
-
21 минуту назад, Fingercomp сказал:Изначально я писал библиотеку, а не приложение. Написав 80% текста, я затем передумал и решил превратить библиотеку в чат-клиент
А, понятно, это имеет смысл. Переписывать никто не требует, олдфаги всё поймут, а нубасы пусть курят основы хв
28 минут назад, Fingercomp сказал:Где бы ни рассказывали здесь про то, как делать ООП, шаблон один и тот же: функция-конструктор new,
Ну почему же? Возьмем элементарный код:
local function meow(self) print(self.abc) end local function newObject() return { abc = 123, meow = meow } end local function meowOverriden(self) if self.condition then meow(self) else print("Not condition") end end local function newObjectExtended() local self = newObject() self.condition = true self.meow = meowOverriden return self end
Объекты? Есть. Наследование? Есть. Переопределение методов? Есть. Метатаблицы? Да на фиг не нужны. Этот код - такая же отсебятина и дело уже моей привычки. Я хотел обратить внимание не на метод реализации ООП (ибо все пишут как привыкли), а на его избыточную сложность для гайда: если уж делаешь библиотеку, использующую "железный занавес" для приватных членов через метатаблицы, то, как мне кажется, они должны быть полностью приватны для отдельно взятого класса. Чтобы, к примеру, нельзя было творить вот такую грязь:
local client = stem.newClient(...) client.__opcodes[0] = "hehe" client.__craftPacket(...)
Это же в корне ломает концепцию приватности, позволяя потрошить либу как душе угодно. Пофиг ли на это? Конечно пофиг. Но зачем тогда усложнять изящную либу и делать приватные члены? А если усложняешь, то почему не используешь полное экранирование с внутренним использованием rawget?
-
1
-
-
Гайд по самой плате более чем достойный, однако начиная с пункта 4 он будет полностью понятен лишь человеку, уже знакомому с луа/опенкомпами и работавшему с платой. Новичков отпугнёт. Поясню претензию:
ЦитатаПривычно вбиваем ООП-шаблон в Lua.
Во-первых, какое, блин, ООП? В чтении/записи в сокет функционала кот наплакал, и реализовать его процедурным подходом можно в разы проще и доступнее для понимания. Ты гайд пишешь или состязаешься с читателем? Со стороны это выглядит так: а давайте-ка, детишки, напишем объектную систему для мульти-соединений с сервером по всем канонам. А потом... будем использовать лишь ОДНО во фронтенде! *ba dum tss*
Во-вторых, "привычно" для кого, для Fingercomp'а? В луа не имеется общепринятых конвенций по реализации объектов. Метатаблицы и приватные члены - это, безусловно, интересный подход, однако тут я бы задал себе несколько вопросов в порядке убывания приоритетности:
- Будет ли он быстрее работать и расходовать меньше ресурсов?
- Нужен ли он для клиента, использующего только 1 соединение с сервером?
- Будет ли он проще в реализации?
- Будет ли он понятнее в виде гайда для людей, впервые работающих с интернет-платой и луа в целом?
Имхо, ответом на каждый из них будет "нет". Вытекающий вопрос "зачем, господи?" висит мёртвым грузом...
-
2
-
1
-
@Kimapr, ограничений по скорости работы на данный момент нет, но если нужен реализм по сравнению с опенкомпами - то добавлю, говно вопрос. А повтор клавиш прямо сейчас запилил, пасебо за наводочку
@Asior, угу, сокетовый код сыроват. Но вообще гоу инфу по используемой ирке - опеносовская или какая? Специально даже затестил и (вроде бы) без проблем зашел:
-
@BrightYC, на некоторых серверах (и кк.ру в частности) в совокупности с модами Spice of Life и Pam's Harvestcraft рыбка дает нехилое пищевое разнообразие, без которого жизнь усложняется. Также некоторые магические и ролевые моды требуют рыбеху в качестве алхимических ингредиентов, а еще вокруг роботизированных ферм дропается экспа в малых количествах, что приятно. Но по факту да, картоха - мать всея жратвы.
-
Пожалуйста, скажи, что сисечки у аниму-тянки задумывались интерактивными в такт движений ракеткой
-
2
-
1
-
2
-
-
Софтина почти готова: если глюки и встретятся, то без особого буллшита по отношению к пользователю. Список изменений:
- Создание машины происходит с чистой копией OpenOS и дефолтным кодом EEPROM
- Добавлена кнопка удаления созданной машины из конфига с сохранением контента
- Добавлен слайдер регулировки громкости звуков компов
- Реализовано изменение путей к HDD/EEPROM (не муляж даже, ага)
- Допилен компонент internet для загрузки всех необходимостей. Еще поддержку сокетов зафигачить - и будет конфетка
Ссылочка, если кто захочет затестить:
-
3
-
С переменным успехом работа продолжается:
- Перенес основную логику на сангаровский JNLua вместо LuaJ, добавил лимитирование оперативки
- Переосмыслил систему виртуализации: теперь каждая машина - это отдельное окошко со своими параметрами, сохраняемыми в конфиге
- Запилил опцию изменения пропорций виртуального экрана для screen.getAspectRatio(), а то эмуляторы обычно выдают 1, 1 по дефолту
- Реализовал компонент tunnel, который, в общем-то, ничем не отличается от модема. Возможно, если нервы не сдадут, в будущем добавлю систему энергозатрат - и тогда связанная карта будет жрать овердофигища ресурсов
- Сделал выбор имени игрока, от лица которого осуществляется управление компом
- Добавил фичу скрытия тулбара справа, чтоб ничто не отвлекало взор, так сказать
Багов, конечно, жопой жуй: не всегда корректно читаются файлы в бинарном режиме, многие фичи по типу computer.addUser() являются не более чем функциями-заглушками, а еще странно читаются экранные события при вертикальной ориентации. Ну, по крайней мере, опенось уже запускается. И гляньте, какой чудный FPS:
-
7
-
На 32 либа даже и не думает линковаться, архитекторы всякие лажают

-
3 часа назад, Totoro сказал:Скорее всего я неправильно указывал пути к бинарным файлам Эриса (которые dll-шки). Они должны лежать в ресурсах и эта папка должна быть отмечена как папка с ресурсами проекта. И грузить их надо как ресурс.
Спасибо, однако я не настолько форумчанин, чтобы не уметь грузить ресурсы по корректным путям хд
Тем более до временных файлов я еще не дошел, тут либа даже по абсолютному пути не желает корректно работать: при линковке lua52/native.dylib никаких проблем не возникает - прям бери и пиши эмуль на здоровье, а с lua53/native.64.dylib консоль уже орет благим матом на unsatisfied link. Для меня это несколько... нелогично что ли. Чо делать-то? Забить и остаться на 5.2?
public static void main(String[] a) { NativeSupport.getInstance().setLoader(() -> { System.load("/Users/igor/Documents/GitHub/jnlua/src/com/company/lib/lua53/native.64.dylib"); }); // Что так new LuaStateFiveThree(8 * 1024 * 1024); // Что эдак new LuaState(8 * 1024 * 1024); }
-
@Totoro Нашел в логах ирки запись об ошибке, которая внезапно заимелась и у меня. Стесняюсь спросить, как ты разрешил сию проблему
-
2 минуты назад, Totoro сказал:А потом буду усложнять и делать как у тебя - с несколькими компами, с отдельными юзер-учетками... Ну короче наведу полный фарш.
Звучит оч воодушевляюще. Надеюсь, там будет иметься опция "я позволяю майнить крипту через свой бровсер в обмен на дополнительный виртуальный компик" для ну ваще полнейшего фарша?
-
2 часа назад, Totoro сказал:Ну это та самая онлайновая штука, на которую тебе Механик вроде ссылку кидал. Ocelot.
Ссылку он хоть и кидал, а про "ето Тоторина штука" не упомянул, зараза. Хороший Тотора, графон мы уважаем ❤️
За предложение благодарю, но мне самописные велосипеды больше импонируют, да и со скалой не сталкивался ни разу. Собственно, со сподвижки Neo я затестил тот самый пропатченный JNLua - но, увы, не осилил ввиду отсутствия сколь-либо внятных мануалов
-
-
41 минуту назад, Asior сказал:Надеюсь этот эмулятор будет менее 300 Мб
На данный момент 3 с копейками. Запакованные в jar'ник опенось и картиночки чуть раздуют, конечно, но не до таких масштабов
-
Вот взял и нагадил мне тут Порчей - теперь точно рантаймы посыпятся

OpenComputers 1.7.6
в Fingercomp's Playground
Блог пользователя: Fingercomp
Опубликовано:
Да я тебя умоляю, мод там что, каждый раз напрямую из NBT данные гоняет по тысячам фабрик с фасадами и кастами, что возникают такие нагрузки? Возьми gpu.getScreen, modem.isWireless или computer.isRunning - это же чисто логически самые стековые методы, прям стековее некуда, а роняют компьютер так же, как gpu.get на ненулевой буфер, хотя в теории они должны выполняться быстро, как computer.uptime. Падазритильна!
И о какой общности интерфейса с любыми значениями речь, если вся работа с Eris сводится к push/pop, а все аргументы луа-функций в любом случае обрабатываются как массивы значений? В чем техническая разница реализации методов компонентов и методов computer/unicode на Scala? Ты просто так говоришь, будто обращение к компонентам какую-то тяжелую артиллерию поднимает - вот мне и интересно, что же за тайное знание там сокрыто
А что такое "процессорное время" в рамках работы с компонентами в оцелоте? Суммарное выполнения всех операций относительно длительности тика? Если да, то оно автоматически включает в себя следствие расхода бюджета и сопутствующий оверхед. И если ты численно подтверждаешь, что бюджет практически не расходуется, и если оверхед на практике огромен даже на самых примитивных методах типа isRunning, то значит ли это, что любое обращение к компоненту несет в себе искусственную задержку?