ECS
-
Публикации
533 -
Зарегистрирован
-
Посещение
-
Победитель дней
203
Сообщения, опубликованные пользователем ECS
-
-
Очень даже удобно, что если где-то доигрался с computer.pullSignal, можно всё равно остановить программу
И очень даже неудобно, если требуется запретить прерывание софтины в частности. Если я желаю остановить выполнение зависшего скрипта, использовать фильтры и листенеры, то, очевидно, воспользуюсь библиотекой event, в противном случае я стану использовать нативный метод pullSignal. Увы, эту возможность у кодеров под OpenOS нагло отняли и навязали подмену функции без разумного объяснения причин. Высказывание автора о том, что он "never liked the user solution to be change this openos internal method" я разумным счесть не могу, ибо на производительность OpenOS это никак не повлияет, а немаловажная фича была слита в унитаз. Это не разумная причина, а субъективная придурь, и именно поэтому я и использовал термин "ерунда", и именно поэтому решение ерундовое
-
в версиях новых OpenOS интеррапт обрабатывается в том числе и в computer.pullSignal (он переопределяется в /lib/event.lua)Фига, не ждал от них подобной ерунды, еще один повод в копилку "отказаться от опеносовской либы". Если по теме, то проверил следующий код на последней версии опенкомпов, интерруптинг отключается без проблем:
event.shouldInterrupt = function() return false end event.shouldSoftInterrupt = event.shouldInterrupt
-
1
-
-
Простым решением проблемы будет использование computer.pullSignal() вместо event.pull(), убрав тем самым поддержку прерывания скрипта. В качестве альтернативы предлагаю эквивалентную по структуре либу, где для отключения прерывания необходимо поставить флаг event.interruptingEnabled = false
-
@@Zer0Galaxy, кстати, чет похожее писал давненько. Работало сносно, хоть это и не полноценный мультитрединг:

-
1
-
-
Мини-обновление: добавлен виджет GUI.filesystemChooser для удобной навигации по файловой системе и выбора файлов/папок пользователем. Также поддерживаются фильтры расширений файлов:

-
4
-
-
Да, но такие программы должны слушать событие "screen_resized", чтобы сразу обновить свои переменные в соответствии с новым размером окна.Ну, в современных фреймворках при изменении размера окна генерируется банальный ивент, и содержимое окна лишь "обрезается" в соответствии с его границами. А уж изменять геометрию содержимого или оставлять прежней - это задача программиста прикладного ПО, так что не вижу в прослушке событий ничего плохого.
К примеру, в QT это реализовывается так:
void MyMainWindow::resizeEvent(QResizeEvent* event) { QMainWindow::resizeEvent(event); // Do something } -
Не нашел в интернете алгоритм Питера Ширли, да и его в целом, выскакивает какой-то музыкант) Можно узнать где вы нашли его алгоритм? Хотя бы ссылку или книгу, может у него и другие эффективные алгоритмы есть.
Спасибо за советы, приму к сведению и постараюсь применить их в новой версии кода

Книга "Fundamentals of Computer Graphics", хоть она и не очень: есть пара интересных алгоритмов по быстрой растеризации примитивов, но именно что лишь пара. Да и те пришлось изрядно оптимизировать, чтобы GC не грузили.
-
2
-
-
Годная софтинка. Пожалуй, стырю в качестве скринсейвера, если не против. Есть, правда, парочка деликатных моментов: во-первых, отрисовка линий через atan/sin/cos хоть и проста, но крайне неэффективна. Рекомендую использовать следующий код, основанный на модифицированном алгоритме Питера Ширли и предназначенный специально для низкопроизводительных машин (значительно быстрее, чем классический алгоритм Брезенхема):
local function line(x1, y1, x2, y2, color) local inLoopValueFrom, inLoopValueTo, outLoopValueFrom, outLoopValueTo, isReversed, inLoopValueDelta, outLoopValueDelta = x1, x2, y1, y2, false, math.abs(x2 - x1), math.abs(y2 - y1) if inLoopValueDelta < outLoopValueDelta then inLoopValueFrom, inLoopValueTo, outLoopValueFrom, outLoopValueTo, isReversed, inLoopValueDelta, outLoopValueDelta = y1, y2, x1, x2, true, outLoopValueDelta, inLoopValueDelta end if outLoopValueFrom > outLoopValueTo then outLoopValueFrom, outLoopValueTo = outLoopValueTo, outLoopValueFrom inLoopValueFrom, inLoopValueTo = inLoopValueTo, inLoopValueFrom end local outLoopValue, outLoopValueCounter, outLoopValueTriggerIncrement = outLoopValueFrom, 1, inLoopValueDelta / outLoopValueDelta local outLoopValueTrigger = outLoopValueTriggerIncrement for inLoopValue = inLoopValueFrom, inLoopValueTo, inLoopValueFrom < inLoopValueTo and 1 or -1 do if isReversed then -- setPixel(outLoopValue, inLoopValue, color) else -- setPixel(inLoopValue, outLoopValue, color) end outLoopValueCounter = outLoopValueCounter + 1 if outLoopValueCounter > outLoopValueTrigger then outLoopValue, outLoopValueTrigger = outLoopValue + 1, outLoopValueTrigger + outLoopValueTriggerIncrement end end endВо-вторых, я бы использовал либу буферизации графики, чтобы не было "промигиваний", и была возможность выставлять хоть 50 линий за раз. Также она уже имеет функции растеризации отрезков, в том числе полупиксельных:

-
5
-
-
Библиотека обновлена. Исправлены мелкие баги, а также добавлено несколько вкусных плюшек:
• Появилась возможность создания автоматических анимаций виджетов:

• Контекстное меню заимело фичу скроллинга контента, а также поддержку вложенных контекстных меню:

• Значительно улучшен GUI.layout, заимев поддержку абсолютного и релятивного размеров ячеек, возможность выравнивания и отступов по произвольному краю, возможность установки расстояния между элементами, а также фиттинга элементов по размеру ячейки:


• Появились два дополнительных варианта отрисовки GUI.button, а также их adaptive-аналоги:

• Появился виджет GUI.brailleCanvas, позволяющий быстро и просто отрисовывать мелкую графику при помощи шрифта Брайля:

-
7
-
-
Это что за программы? Есть пример? Я привык, что всегда нужно pullSignal писать в программе, чтобы она работала
local redstone = require("component").redstone while true do redstone.setOutput(1, math.random(15)) endЧто примечательно, эту софтину возможно завершить только путем отсоединения редстоун-компонента. Как верно подметил eu_tomat, каждое обращение к нему ведет себя аналогично .pullSignal(), однако не вызывает его
-
Есть пример рабочей реализации? Чтобы две-три программы работали, рисовали графику. Я бы посмотрел исходникиА то. Как раз даже гифочка припасена на всякий пожарный. Вся ОСька по сути - это один жирный контейнер, а палитра и магазин приложений - вложенные контейнеры, стилизованные под окна. Сырец либы тут, дока тут

-
4
-
-
Многозадачность можно реализовать двумя путями:
Есть третий принципиально отличающийся вариант: обработка нескольких приложений-окон в общем потоке-контейнере. Из плюсов тут стоит выделить максимальное быстродействие, т.к. выполнение скрипта не будет искусственно замедлено множественными yield() в подмененных функциях, а также простоту написания такого концепта. Из минусов - поддерживать многозадачность будет лишь то ПО, которое написано под данную ОС, все остальное будет работать в штатном режиме. А также имеет место быть стабильный краш главного потока при краше любого из приложений - проблема решается изоляцией пространства приложения от контейнера и кешированием его состояния.
-
Переменная весит сколько весит ссылка в ОS.
А вот объект на который ссылается переменная весит в зависимости от типа.
Как ты понимаешь ссылка это не объект на стеке и она ссылается на объект в твоей мапе который ты и так хранишь.
nil помогает в том случае если у тебя переменная находится в скопе из которого ты часами не выходишь.
Для справки: каждая переменная-указатель на таблицу или функцию в Lua весит в равной мере 9 байт.
А теперь немного сухих расчетов: представим простейшую трехмерную сцену из восьми кубиков. Каждый куб имеет 8 вершин, каждая вершина - это трехмерная таблица-вектор с числовой индексацией, в сумме кушающая 40 (table) + 8 (double) * 3 = 64 байта. Все вершины заносятся в массив вершин сцены для минимизации расхода памяти. Также каждый куб имеет таблицу-линковщик, содержащую индексы вершин, образующие треугольники для отрисовки куба в количестве 12 штук. Каждый треугольник с ссылками на три вершины - это такой же трехмерный вектор, кушающий все так же 64 байта. Итого получаем 64 * 8 = 512 байт на вершины и 64 * 12 = 768 байт на линковку вершин, итого 1280 байт на куб. Сколько у нас там их? Восемь? Итого трехмерная сцена выжрет 1280 * 8 = 10240 байт = 10 КБайт. Это тот минимум, который необходим для старта отрисовки графики, материалы и текстуры для простоты рассматривать не будем. Если же использовать локальные переменные-сокращалки, то расход памяти взлетит по экспоненте.
Чтобы пруфануть это более наглядно, привожу выдержку из кода движка, содержащую основной цикл, отвечающий за получение соответствующих вершин через треугольники:
for triangleIndex = 1, #OCGL.triangles do vertex1[1], vertex1[2], vertex1[3] = renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][1]][1], renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][1]][2], OCGL.vertices[OCGL.triangles[triangleIndex][1]][3] vertex2[1], vertex2[2], vertex2[3] = renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][2]][1], renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][2]][2], OCGL.vertices[OCGL.triangles[triangleIndex][2]][3] vertex3[1], vertex3[2], vertex3[3] = renderer.viewport.xCenter + OCGL.vertices[OCGL.triangles[triangleIndex][3]][1], renderer.viewport.yCenter - OCGL.vertices[OCGL.triangles[triangleIndex][3]][2], OCGL.vertices[OCGL.triangles[triangleIndex][3]][3] material = OCGL.triangles[triangleIndex][4] ...
Также привожу скриншот с результирующим FPS в 7 единиц и расходом оперативной памяти в 46% от максимального запаса (4 Мб)

А теперь намутим-ка локальных сокращений для минимизации нагрузки на ЦП:
local ti, ve1, ve2, ve3 for triangleIndex = 1, #OCGL.triangles do ti = OCGL.triangles[triangleIndex] ve1, ve2, ve3 = OCGL.vertices[ti[1]], OCGL.vertices[ti[2]], OCGL.vertices[ti[3]] vertex1[1], vertex1[2], vertex1[3] = renderer.viewport.xCenter + ve1[1], renderer.viewport.yCenter - ve1[2], ve1[3] vertex2[1], vertex2[2], vertex2[3] = renderer.viewport.xCenter + ve2[1], renderer.viewport.yCenter - ve2[2], ve2[3] vertex3[1], vertex3[2], vertex3[3] = renderer.viewport.xCenter + ve3[1], renderer.viewport.yCenter - ve3[2], ve3[3] material = OCGL.triangles[triangleIndex][4] ...
Результат плачевный. Не замечено ни прироста, ни убыли значений FPS, однако расход памяти возрос до 61%. Магия? Нет, особенности конкретного ЯП и его интеграции в виде мода.

-
1
-
1
-
-
RccHD немного не убедительно написал, я попробую его поправить.
- выполнение buffer.currentFrame[index]
-- обращение к переменной buffer
-- обращение к полю объекта. Но мы имеем дело с lua, по-этому buffer это HashMap а currentFrame это ключ.
- расчёт hash("currentFrame")
- определение смещения по хешу
- выборка списка (может дерева) элементов по смещению из массива
- разрешение коллизий (дорого)
- ...
Спасибо за пояснение очевидного. Ты забываешь про буфер хешмапы, ускоряющий поиск часто используемых объектов - в большинстве случаев описанные тобой операции банально "скипаются", особенно в нашем контексте, где используется обращение к одним и тем же вложенным таблицам.
Если у вас есть проблемы со своевременной очисткой памяти, то можно вручную вызвать сборку мусора.
Ручной вызов GC в OpenComputers невозможен, эта фича отключена авторами мода по понятным причинам. Если бы я мог активировать сборку мусора - то неужели стал бы писать сюда о проблемах с локальными переменными?
И переменная весит ровно 64 бита.
Переменная весит столько, сколько определено ее типом: строки занимают 17 байт + длина самой строки, таблица кушает 40 байт + ее содержимое, каждая функция - 20 байт + локальные данные. Пожалуйста, не пиши глупости без знания матчасти.
Мне кажется, что кто-то просто забывает писать ключевое слово local.
А мне кажется, что кто-то слишком много умничает не по делу. Использование локальных переменных - чуть ли не основа основ при кодинге на любом ЯП. И присвоение переменной nil, как оказалось, отнюдь не ускоряет ее очистку из памяти, ибо, разумеется, этот вариант мы также рассматривали.
-
2
- выполнение buffer.currentFrame[index]
-
Всегда считал, что переменные(они же указатели на объекты) не могут занимать много памяти... Хотя бы потому что исходники библиотек OpenOS прямо-таки напичканы переменными. Может дело все-таки не в таких мелочных деталях как переменные, а в самой реализации?
В большинстве случаев дело именно в реализации, да. Если имеется какой-нибудь вшивый цикл на пару итераций, то куда выгоднее использовать локальные переменные, как ты и предлагал, чтобы минимизировать нагрузку на ЦП, это логично. Однако в нашем случае рассматривается функция, вызываемая весьма часто со множеством вложенных циклов и способная в самый неподходящий момент перегрузить сборщик мусора. В принципе, если памяти хватает - то и фиг с ним. Вообще за наводку на идею ускорения спасибо, можно вынести локальные сокращения за пределы циклов отрисовки - и тем самым сэкономить тики ЦП без ущерба для памяти. Хотя придется изрядно повозиться, да
А насчет исходников OpenOS - с каких это пор они стали эталоном грамотного и эффективного кода? Лично я вообще не понимаю, что в ней может кушать столько памяти (пс-с-ст, более 200 КБайт по дефолту, жуть какая). Хотя приведенный тобой пример вносит определенную ясность хд
-
1
-
-
По поводу нагрузки на ЦПУ: писать "buffer.currentFrame[index]" плохо так как система будет каждый раз выполняет следующие действия: 1) получает значение переменной "buffer" 2) получает поле "currentFrame" объекта "buffer" 3) получает поле "index" объекта "buffer.currentFrame" А если хранить это значение в переменной, то будет одно действие: 1) получает значение переменной "el0
Увы, такой подход крайне нерационален. Безусловно, визуально куда проще выделить локальную переменную под жирную таблицу с множеством вложенных обращений, сэкономив тем самым несколько тиков - однако если бы я использовал такой подход при написании требовательного софта, то он вылетал бы с not enough memory еще до старта. Примером может послужить наш 3D-движок: сборщик мусора банально не успевал очищать локальные переменные-указатели на таблицы векторов при отрисовке сцен, и ошибка о нехватке памяти вылезала как результат. Сократив подобный "некорявый код" до минимума, мы смогли запустить движок всего лишь на 2 МБ RAM. Так что лучше помучиться с лишними буковками, нежели писать неоптимизированное в данном контексте ПО. Имхо, конечно же
-
1
-
-
О халявный ключик для Яндекс-переводчика =)
Он бесплатный с ограничением до 1 млн символов в сутки, увы. Но побаловаться сойдет хд
-
1
-
-

Не, ну а чо, почему нет?
Команда для установки:
pastebin run 0wFnKD5k
Команда для запуска:
/Translate/Main.lua
-
8
-
-
блиотека довольно коряво в плане стиля написания кода(мое личное мнение)Ну блин, стараешься тут, стараешься, разбивая код на суб-сегменты по классическим идиомам проектирования, минимизируя нагрузку на оперативку и ЦПУ, а потом его "корявым" называют. Обидно

А вообще интересно, каким образом ты уменьшил размер сырцов в 5 раз - уж не путем ли удаления половины "не нужных" для твоей ОС элементов? Го инфу, любопытно стало.
-
4
-
-

Cобсна, программа проста, как три копейки: левый и правый клики по спиннеру меняют его цвет, а нажатие на любую клавишу позволяет выйти. Надеюсь, любители особых извращений оценят ее по достоинству.Команда для установки:
pastebin run MMvSd2be
Команда для запуска:
/Spinner/Main.lua
-
3
-
-
local filesystem = require("filesystem") --------------------------------------------------------------------- function table.unserialize(serializedString) checkArg(1, serializedString, "string") local success, result = pcall(load("return " .. serializedString)) if success then return result else return nil, result end end function table.fromFile(path) checkArg(1, path, "string") if filesystem.exists(path) then if filesystem.isDirectory(path) then error("\"" .. path .. "\" is a directory") else local file = io.open(path, "r") local data = table.unserialize(file:read("*a")) file:close() return data end else error("\"" .. path .. "\" doesn't exists") end end --------------------------------------------------------------------- local myTable = table.fromFile("/myFileWithTable.lua")Десериализация таблицы на чистом луа без лишних библиотек
-
local function sleep(timeout) local deadline = computer.uptime() + (timeout or 0) while computer.uptime() < deadline do computer.pullSignal(deadline - computer.uptime()) end endДержи простейший вариант задержки, учитывающий возможные ивенты, если дефолтный os.sleep юзать не можешь/не хочешь
-
Может заменить округление на целочисленное деление на 1?
10мультов операций деления на 1 и округления вниз

iterCount = 10000000 print(iterCount, 'cycles') startTime = os.clock() for i=1,iterCount do a=1.1//1 end print('1.1//1:', os.clock()-startTime) startTime = os.clock() for i=1,iterCount do a=math.floor(1.1) end print('math.floor(1.1):', os.clock()-startTime)Ага, спасибо. Я вообще не в курсе был про вариант целочисленного деления с двумя слешами в 5.3, заменим в ближайшее время
UPD: Существенной разницы при отрисовке сложных сцен не заметно, но сам факт приятен
-
1
-
-
Ну это, конечно, относилось не конкретно к этой либе, а к инсталлятору MineOS в целом - ребята ставили, а оказывалось, что либа сериализации затиралась. Я, как говорил, уверен, что это не было сделано специально, но иногда можно не заметить.А, тогда понятно. В майноси чутка иная сериализация - вот и крашится, угу.11
Печально, что с репозиторием такое мнение. Посмотрю, как можно обойти установку одних и тех же файлов в миллионах мест. Либы заменить нечем, особенно буферизацию.Когда-нибудь, когда горы полетят по ветру, как опавшие листья... возможно, появится мыслишка с этим поколупаться. Но не сейчас точно. Чертовы Вексатосы!
-
1
-

MineOS
в Операционные системы
Опубликовано:
Раз уж на форуме появился специализированный раздел, посвященный операционным системам, то грех не выложить свою. Сама система является графической оболочкой к дефолтной OpenOS со множеством собственных библиотек, основной упор при ее написании делался на визуальную составляющую и общее быстродействие.
Ключевые особенности:
Установка:
Для запуска инсталлера введите следующую команду:
Перед вами появится симпатичный интерфейс, где вы сможете выбрать параметры установки: к примеру, загружать ли все имеющиеся приложения, либо оставить только системные, а также загружать ли обои рабочего стола. Лицензионное соглашение шуточное, всерьез можно не воспринимать.
Исходники:
https://github.com/IgorTimofeev/MineOS
Люди, прямо или косвенно участвовавшие в разработке:
Тимофеев Игорь - рефакторинг, оптимизация и вылизывание кода
Трифонов Глеб - разработчик формата изображений OCIF и методов цветовой обработки
Веревкин Яков - консультант по вопросам векторно-матричных преобразований
Шестаков Тимофей - специалист по UI/UX-дилеммам
Смирнов Алексей - тестировщик ПО
Богушевич Виктория - синтаксический корректировщик и отвлекающий фактор
Витвицкая Яна - позитивистский мотиватор и не менее отвлекающий фактор
Какой-то Андрей - эксперт в области оценки красоты кода
Ярычев Никита - компаньон в обсуждениях философских нюансов
Пакин Максим - автор нескольких приложений
Тиунов Дмитрий - консультант по нюансам веб-запросов
Маяковский Константин - товарищ со уникальным духовно-пофигистическим характером
Сазонов Слава - автор пары оптимизационных моментов и любитель кратких диалогов
Омелаенко Максим - анализатор рынка ПО и конкурентных решений
Просин Михаил - генератор мотивации по генерации идей по улучшению ПО
Чернышева Дарья - моральная поддержка команды
Палиев Егор - очень хотел в этот список