Перейти к содержимому

ECS

Гуру
  • Публикации

    533
  • Зарегистрирован

  • Посещение

  • Победитель дней

    203

Все публикации пользователя ECS

  1. Интересно, работает ли либа на Lua 5.2? Возможный диапазон целых чисел на прошлой версии отличается от 5.3:
  2. Раз уж на форуме появился специализированный раздел, посвященный операционным системам, то грех не выложить свою. Сама система является графической оболочкой к дефолтной OpenOS со множеством собственных библиотек, основной упор при ее написании делался на визуальную составляющую и общее быстродействие. Ключевые особенности: Многозадачность Оконный интерфейс с двойной буферизацией графики Поддержка анимаций, обоев, заставок и цветовых схем Поддержка языковых пакетов и локализации ПО Поддержка авторизации пользователя по паролю и биометрике Поддержка обмена файлами по локальной сети через модемы Поддержка клиентского подключения к реальным FTP-серверам Система отчетов об ошибках с возможностью отправки информации разработчикам Магазин приложений с возможностью публикации собственных творений и системой пользовательских рейтингов Интегрированная IDE с отладчиком и значительное количество разнообразного прикладного ПО Открытое системное API и подробная иллюстрированная документация к библиотекам Собственная прошивка EEPROM с возможностью выбора/форматирования загрузочного тома и восстановлением через интернет Частичная совместимость с OpenOS-софтом Установка: Для запуска инсталлера введите следующую команду: wget -f https://raw.githubusercontent.com/IgorTimofeev/MineOS/master/Installer/BIOS.lua /tmp/bios.lua && flash -q /tmp/bios.lua && reboot Перед вами появится симпатичный интерфейс, где вы сможете выбрать параметры установки: к примеру, загружать ли все имеющиеся приложения, либо оставить только системные, а также загружать ли обои рабочего стола. Лицензионное соглашение шуточное, всерьез можно не воспринимать. Исходники: https://github.com/IgorTimofeev/MineOS Люди, прямо или косвенно участвовавшие в разработке: Тимофеев Игорь - рефакторинг, оптимизация и вылизывание кода Трифонов Глеб - разработчик формата изображений OCIF и методов цветовой обработки Веревкин Яков - консультант по вопросам векторно-матричных преобразований Шестаков Тимофей - специалист по UI/UX-дилеммам Смирнов Алексей - тестировщик ПО Богушевич Виктория - синтаксический корректировщик и отвлекающий фактор Витвицкая Яна - позитивистский мотиватор и не менее отвлекающий фактор Какой-то Андрей - эксперт в области оценки красоты кода Ярычев Никита - компаньон в обсуждениях философских нюансов Пакин Максим - автор нескольких приложений Тиунов Дмитрий - консультант по нюансам веб-запросов Маяковский Константин - товарищ со уникальным духовно-пофигистическим характером Сазонов Слава - автор пары оптимизационных моментов и любитель кратких диалогов Омелаенко Максим - анализатор рынка ПО и конкурентных решений Просин Михаил - генератор мотивации по генерации идей по улучшению ПО Чернышева Дарья - моральная поддержка команды Палиев Егор - очень хотел в этот список
  3. И очень даже неудобно, если требуется запретить прерывание софтины в частности. Если я желаю остановить выполнение зависшего скрипта, использовать фильтры и листенеры, то, очевидно, воспользуюсь библиотекой event, в противном случае я стану использовать нативный метод pullSignal. Увы, эту возможность у кодеров под OpenOS нагло отняли и навязали подмену функции без разумного объяснения причин. Высказывание автора о том, что он "never liked the user solution to be change this openos internal method" я разумным счесть не могу, ибо на производительность OpenOS это никак не повлияет, а немаловажная фича была слита в унитаз. Это не разумная причина, а субъективная придурь, и именно поэтому я и использовал термин "ерунда", и именно поэтому решение ерундовое
  4. Фига, не ждал от них подобной ерунды, еще один повод в копилку "отказаться от опеносовской либы". Если по теме, то проверил следующий код на последней версии опенкомпов, интерруптинг отключается без проблем: event.shouldInterrupt = function() return false end event.shouldSoftInterrupt = event.shouldInterrupt
  5. Простым решением проблемы будет использование computer.pullSignal() вместо event.pull(), убрав тем самым поддержку прерывания скрипта. В качестве альтернативы предлагаю эквивалентную по структуре либу, где для отключения прерывания необходимо поставить флаг event.interruptingEnabled = false
  6. @@Zer0Galaxy, кстати, чет похожее писал давненько. Работало сносно, хоть это и не полноценный мультитрединг:
  7. Мини-обновление: добавлен виджет GUI.filesystemChooser для удобной навигации по файловой системе и выбора файлов/папок пользователем. Также поддерживаются фильтры расширений файлов:
  8. Ну, в современных фреймворках при изменении размера окна генерируется банальный ивент, и содержимое окна лишь "обрезается" в соответствии с его границами. А уж изменять геометрию содержимого или оставлять прежней - это задача программиста прикладного ПО, так что не вижу в прослушке событий ничего плохого. К примеру, в QT это реализовывается так: void MyMainWindow::resizeEvent(QResizeEvent* event) { QMainWindow::resizeEvent(event); // Do something }
  9. Книга "Fundamentals of Computer Graphics", хоть она и не очень: есть пара интересных алгоритмов по быстрой растеризации примитивов, но именно что лишь пара. Да и те пришлось изрядно оптимизировать, чтобы GC не грузили.
  10. Годная софтинка. Пожалуй, стырю в качестве скринсейвера, если не против. Есть, правда, парочка деликатных моментов: во-первых, отрисовка линий через 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 линий за раз. Также она уже имеет функции растеризации отрезков, в том числе полупиксельных:
  11. Библиотека обновлена. Исправлены мелкие баги, а также добавлено несколько вкусных плюшек: • Появилась возможность создания автоматических анимаций виджетов: • Контекстное меню заимело фичу скроллинга контента, а также поддержку вложенных контекстных меню: • Значительно улучшен GUI.layout, заимев поддержку абсолютного и релятивного размеров ячеек, возможность выравнивания и отступов по произвольному краю, возможность установки расстояния между элементами, а также фиттинга элементов по размеру ячейки: • Появились два дополнительных варианта отрисовки GUI.button, а также их adaptive-аналоги: • Появился виджет GUI.brailleCanvas, позволяющий быстро и просто отрисовывать мелкую графику при помощи шрифта Брайля:
  12. local redstone = require("component").redstone while true do redstone.setOutput(1, math.random(15)) end Что примечательно, эту софтину возможно завершить только путем отсоединения редстоун-компонента. Как верно подметил eu_tomat, каждое обращение к нему ведет себя аналогично .pullSignal(), однако не вызывает его
  13. А то. Как раз даже гифочка припасена на всякий пожарный. Вся ОСька по сути - это один жирный контейнер, а палитра и магазин приложений - вложенные контейнеры, стилизованные под окна. Сырец либы тут, дока тут
  14. Есть третий принципиально отличающийся вариант: обработка нескольких приложений-окон в общем потоке-контейнере. Из плюсов тут стоит выделить максимальное быстродействие, т.к. выполнение скрипта не будет искусственно замедлено множественными yield() в подмененных функциях, а также простоту написания такого концепта. Из минусов - поддерживать многозадачность будет лишь то ПО, которое написано под данную ОС, все остальное будет работать в штатном режиме. А также имеет место быть стабильный краш главного потока при краше любого из приложений - проблема решается изоляцией пространства приложения от контейнера и кешированием его состояния.
  15. Для справки: каждая переменная-указатель на таблицу или функцию в 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%. Магия? Нет, особенности конкретного ЯП и его интеграции в виде мода.
  16. Спасибо за пояснение очевидного. Ты забываешь про буфер хешмапы, ускоряющий поиск часто используемых объектов - в большинстве случаев описанные тобой операции банально "скипаются", особенно в нашем контексте, где используется обращение к одним и тем же вложенным таблицам. Ручной вызов GC в OpenComputers невозможен, эта фича отключена авторами мода по понятным причинам. Если бы я мог активировать сборку мусора - то неужели стал бы писать сюда о проблемах с локальными переменными? Переменная весит столько, сколько определено ее типом: строки занимают 17 байт + длина самой строки, таблица кушает 40 байт + ее содержимое, каждая функция - 20 байт + локальные данные. Пожалуйста, не пиши глупости без знания матчасти. А мне кажется, что кто-то слишком много умничает не по делу. Использование локальных переменных - чуть ли не основа основ при кодинге на любом ЯП. И присвоение переменной nil, как оказалось, отнюдь не ускоряет ее очистку из памяти, ибо, разумеется, этот вариант мы также рассматривали.
  17. В большинстве случаев дело именно в реализации, да. Если имеется какой-нибудь вшивый цикл на пару итераций, то куда выгоднее использовать локальные переменные, как ты и предлагал, чтобы минимизировать нагрузку на ЦП, это логично. Однако в нашем случае рассматривается функция, вызываемая весьма часто со множеством вложенных циклов и способная в самый неподходящий момент перегрузить сборщик мусора. В принципе, если памяти хватает - то и фиг с ним. Вообще за наводку на идею ускорения спасибо, можно вынести локальные сокращения за пределы циклов отрисовки - и тем самым сэкономить тики ЦП без ущерба для памяти. Хотя придется изрядно повозиться, да А насчет исходников OpenOS - с каких это пор они стали эталоном грамотного и эффективного кода? Лично я вообще не понимаю, что в ней может кушать столько памяти (пс-с-ст, более 200 КБайт по дефолту, жуть какая). Хотя приведенный тобой пример вносит определенную ясность хд
  18. Увы, такой подход крайне нерационален. Безусловно, визуально куда проще выделить локальную переменную под жирную таблицу с множеством вложенных обращений, сэкономив тем самым несколько тиков - однако если бы я использовал такой подход при написании требовательного софта, то он вылетал бы с not enough memory еще до старта. Примером может послужить наш 3D-движок: сборщик мусора банально не успевал очищать локальные переменные-указатели на таблицы векторов при отрисовке сцен, и ошибка о нехватке памяти вылезала как результат. Сократив подобный "некорявый код" до минимума, мы смогли запустить движок всего лишь на 2 МБ RAM. Так что лучше помучиться с лишними буковками, нежели писать неоптимизированное в данном контексте ПО. Имхо, конечно же
  19. Он бесплатный с ограничением до 1 млн символов в сутки, увы. Но побаловаться сойдет хд
  20. Не, ну а чо, почему нет? Команда для установки: pastebin run 0wFnKD5k Команда для запуска: /Translate/Main.lua
  21. Ну блин, стараешься тут, стараешься, разбивая код на суб-сегменты по классическим идиомам проектирования, минимизируя нагрузку на оперативку и ЦПУ, а потом его "корявым" называют. Обидно А вообще интересно, каким образом ты уменьшил размер сырцов в 5 раз - уж не путем ли удаления половины "не нужных" для твоей ОС элементов? Го инфу, любопытно стало.
  22. Cобсна, программа проста, как три копейки: левый и правый клики по спиннеру меняют его цвет, а нажатие на любую клавишу позволяет выйти. Надеюсь, любители особых извращений оценят ее по достоинству. Команда для установки: pastebin run MMvSd2be Команда для запуска: /Spinner/Main.lua
  23. 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") Десериализация таблицы на чистом луа без лишних библиотек
  24. 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 юзать не можешь/не хочешь
  25. Ага, спасибо. Я вообще не в курсе был про вариант целочисленного деления с двумя слешами в 5.3, заменим в ближайшее время UPD: Существенной разницы при отрисовке сложных сцен не заметно, но сам факт приятен
×
×
  • Создать...