eu_tomat
-
Публикации
2 666 -
Зарегистрирован
-
Посещение
-
Победитель дней
331
Сообщения, опубликованные пользователем eu_tomat
-
-
3 часа назад, MrAbad сказал:есть тема, где есть кладесь информации, по-оптимизации кода
Это далеко не кладезь. Синтетические тесты, конечно, полезны для понимания, но их практическая ценность не высока. Нужны какие-то примеры, приближенные к реальности: программа, долго считающая что-то нужное, которая после оптимизации начинает считать хотя бы в два раза быстрее.
3 часа назад, MrAbad сказал:в будущем постараюсь что-то по-глубже делать
Предлагаю начать как раз с этой темы: рассказать, что такое оптимизация, зачем нужна, и как её применять, когда улучшение одного параметра ухудшает другой. И поправить противоречивые моменты, вводящие в заблуждение. Тогда этот урок будет давать какие-то ответы, а не порождать вопросы на ровном месте.
В 01.04.2021 в 06:24, MrAbad сказал:Пустая функция (function() end) занимает 93 байт, пустая функция с return (function() return true end) занимает 102 байт.
Что значит "занимает"? В какой момент? В момент создания функции или на время вызова? Нужно ли вызывать сборщик мусора после вызова функции? Или сборщик мусора тут не поможет, и требуется очищать ссылку на функцию? Значит ли это, что избавление кода от функций всегда полезно для его производительности? Чему учит эта часть урока?
В 01.04.2021 в 06:24, MrAbad сказал:И, кстати, таблицы не сжимаются, то есть если туда запихать 1000 элементов, а потом удалить их, то весить она будет, как будто в ней все еще 1000 элементов
Значит ли это, что очистка элементов таблиц не имеет смысла?
В 01.04.2021 в 06:24, MrAbad сказал:Автоматический сборщик мусора в опенкомпах вроде бы отключен, и вызывается только через os.sleep(0), и то не гарантированно, так что разработчик мода советует его вызывать 10 раз подряд, чтоб уж точно
И еще, автоматический сборщик чистит ТОЛЬКО локальные переменныеА если я обнулил глобальную переменную, содержащую длинную строку, разве занимаемая ей память не будет очищена сборщиком мусора? И что значит, 10 раз подряд? Что мне мешает перемежать вызовы sleep какими-то вычислениями? И что мне мешает заменить вызовы sleep, вызовами методов периферии. И обязательно ли мне каждый раз делать ровно 10 вызовов, или есть способ определить факт вызова сборщика мусора? И как определить, что вообще пора его вызывать?
В 01.04.2021 в 06:24, MrAbad сказал:Не используйте рекурсию функций, а если совсем приспичило, то почаще вставляйте сбор мусора
Насколько чаще? Будет ли правильным вставлять сбор мусора в каждый вызов рекурсивной функции?
В 01.04.2021 в 06:24, MrAbad сказал:Не используйте замыкания (это когда функция возвращает другую функцию)
Замыкание имеет чуть иной смысл. Возвращаемая функция должна использовать внешние по отношению к ней локальные переменные порождающей функции. Тогда будет замыкание.
В 01.04.2021 в 06:24, MrAbad сказал:(Если вы не поняли, что сейчас вообще было, то ищите битовую операцию XOR)
Этот совет дает хотя бы небольшой прирост, из-за того, что нет лишний переменной, но этот плюс нивелируется, если ее удалитьЗдесь я не понял, что сейчас вообще было. Откуда надо удалить переменную , чтобы этот плюс нивелировался? И что за прирост даёт этот совет?
-
-
В 01.07.2015 в 00:28, unknown сказал:Напиши вместо ipairs(arg) просто ipairs({...}), или перед этим впиши arg = {...}
Пытаясь написать свою версию функции print(), я тоже интуитивно применил ipairs({...}). И т.к. функция предполагалась универсальной, я для теста подал в неё аргументы разных типов. В том числе и nil. На нём-то обработка и завершилась, хотя после nil были и другие аргументы.
Я подсмотрел код print из openOS, и там обработка аргументов выглядит примерно так:
function print(...) local args = table.pack(...) for i = 1, args.n do str = args[i] end end
Решение показалось мне недостаточно красивым, и я попытался найти что-то более приятное глазу. Лучшего решения найти не удалось, но поиск привёл меня сюда. Полагаю, универсальное решение пригодится читателям этой темы.
-
2 минуты назад, kifrid сказал:Оно не пишет
Я неудачно задал вопрос. Он заключался в том, как далеко твой планшет находился от дрона в тот момент, когда программа просила подойти ближе.
-
29 минут назад, kifrid сказал:Что делать если при сопряжении выдаёт ошибку. Пишет что надо подойти ближе
А на каком расстоянии от планшета до дрона просит подойти?
В 11.06.2019 в 07:39, BrightYC сказал:Первый запуск сопровождается привязкой дрона к порту(Порт можно увидеть открыв дрона) и адресу беспроводной карты. Из-за этого возможность угнать дрона стремится к нулю, так как для первичной настройки нужно стоять не дальше 5 блоков от дрона.
-
Осталось лишь решить проблему шума. Интервалы времени длительностью 1.6629999990414e-06 вообще ни о чём не говорят на фоне шума измерений. Надо повторять эксперимент в цикле с достаточным количеством итераций.
Например, для проверки одноразового вызова math.sin я бы использовал такие циклы:
for i=1,1e6 do local sin = math.sin x = sin(3) end for i=1,1e6 do x = math.sin(3) end
Но этого тоже недостаточно. Есть разброс значений. Поэтому надо повторять эксперимент какое-то количество раз. Какое именно? Надо вспоминать основы статистики. И если у кого-то эти воспоминания достаточно свежи, дайте совет.
Для дальнейших рассуждений по теме я порылся в своих прошлых наработках, но оказалось, что там я застрял, не дойдя до конца. Но какая-то информация есть.
Сервер нагружен неравномерно. И для выравнивания замеров имеет смысл чередовать циклы экспериментов: Выполнили в цикле один код, сделали короткую паузу, выполнили цикл со вторым кодом, сделал паузу, выполнили цикл с третим, и т.д., по кругу.
Сервер бывает нагружен настолько неравномерно, что некоторые замеры аномально отличаются от среднего значения в болшьую сторону, и их надо бы отбрасывать. Мы же не характеристики сервера измеряем, а сравниваем эффективность кода. Но тут снова нужно аккуратно применять статистику.
В своих прошлых экспериментах я пришёл к выводу, что итоговый код окажется достаточно сложным, что его проще будет вынести в отдельную библиотеку, аккуратно выполняющую замеры.
Один я не готов оценивать глубину этой кроличьей норы, но @Taruu, мы можем попробовать написать такую библиотеку вместе. Также я прошу откликнуться и других форумчан. В тонкой сфере измерений аудит кода никогда не будет лишним. Также нужны идеи. Возможно, всё можно сделать проще, чем мне кажется.
А я попробую в ближайшие дни найти все старые наработки и скомпилировать их во что-то определённое.
-
1
-
-
5 минут назад, Taruu сказал:Тут ошибочка получается. У тебя print в памяти остается ?:/ Так что каждый раз нужно в переименую записывать.
Да, здесь я ошибся. Обе операции не потребляют дополнительную память, но xor всё равно хуже по другим причинам.
@LeshaInc своей картинкой, видимо, намекает на сложность темы, но это сразу было понятно. Тесты, измеряющие код, всегда сложно создавать, потому как кодомерка сама может вносить погрешность.
-
Пффф.. Ну, раз я влез в эту тему, то продолжу обсуждение.
1 час назад, Taruu сказал:os.clock() - показывает как долго запущена программа
Не совсем. Как долго работает компьютер, скажет computer.uptime(), а os.clock() скажет, сколько из этого времени компьютер потратил на, собственно, вычисления. Конечно, с некоторыми оговорками, но в целом именно os.clock() позволяет оценить нагрузку, создаваемую тем или иным кодом на игровой сервер.
2 часа назад, Taruu сказал:Делайте функции в программе локальными. Это работает как и с локализацией существующих функций:
Пример с функцией math.sin и ее локальной версией:
...
Как видно мы получили очень большой прирост в производительности. Почти в два раза! Что уже неплохо.
Так же это особенность работает и на своих функциях.Это грязный эксперимент с неправильной интерпретацией результата. В нём извлечение поля из таблицы выполняется два раза, о чём не упомянуто в описании.
Также эксперимент не сообщает о том, имеет ли смысл создавать локальную переменную для функции math.sin, если её планируется использовать всего два раза. Или пять, например.
2 часа назад, Taruu сказал:X*X вместо X^2
...
Во всех экспериментах маловаты измеряемые интервалы времени. Но в этом они слишком малы. Шум легко может оказаться выше реальной разницы во времени. А шум есть всегда, даже при выполнении кода на оборудовании с избыточной мощностью.
2 часа назад, Taruu сказал:Самый быстрый способ это создать временную переименую и записать одну меняемую переименую в нее.
А здесь как раз именно шум не позволяет увидеть, что a,b = b,a имеет ровно ту же эффективность. Вообще, при интерпретации результатов следует сравнивать полученную разницу с шумовой, чтобы не делать преждевременных выводов.
2 часа назад, Taruu сказал:Если же мы сильно экономим память то нам отлично подойдет побитовый XOR (~)
В этом месте я всё-таки ожидал увидеть экспериментальное подтверждение «эффективности» этого трюка. Но именно это заблуждение надо развеять в первую очередь.
Эксперимент:
local a,b = 23,76 local computer = require("computer") local mem0 = computer.freeMemory() for i=1,1e7 do a,b=b,a end print(mem0 - computer.freeMemory()) -- Результат: 0 for i=1,1e7 do a=a~b b=a~b a=a~b end print(mem0 - computer.freeMemory()) -- Результат: 6631
Результат: Обмен значений переменных через a,b=b,a потребляет ровно 0 дополнительной памяти и быстро работает. Зато обмен посредством XOR и память потребляет, и работает медленно, да ещё и код загромождает.
Я не знаю, почему этот вредный совет транслируют на форумах программистов. Вне сомнений, в арсенале программиста должен быть трюк обмена переменных через исключающее или. Но зачем его тулить к месту и не к месту? Урок же вроде как про оптимизацию кода.
И даже если бы этот трюк оказался эффективным, почему нет упоминания о том, что xor работает не для всех типов переменных?
И раз пошёл такой разговор, разберу предыдущее обсуждение:
В 01.04.2021 в 09:29, Zer0Galaxy сказал:А как на счет такого варианта?
a,b = b,aНа сколько это более/менее производительней чем пример с XORом?
Эффективнее со всех точек зрения.
В 01.04.2021 в 17:50, MrAbad сказал:В Lua эта конструкция создает буферную переменную
Lua для любых операций создаёт буферные переменные для хранения временных результатов. Но, в случае a,b=b,a они уничтожаются незамедлительно в отличие от xor. Операция a,b=b,aтребует на выполнение столько же времени, как три отдельных операции присваивания, но потребления памяти не увеличивает.
-
1
-
-
Изначально я не хотел комментировать этот «урок», т.к. объём комментариев в несколько раз превысил бы изначальный текст. Главная претензия к нему в отсутствии конкретики и каких-либо примеров, позволяющих читателю прийти к тем же выводам.
@Taruu , приведя конкретный пример, спасает этот урок.
Если кто-то хочет продолжить это начинание, я прошу не скидывать все замеры в одну программу, или хотя бы в коде одной программы дробить код на блоки и добавлять короткое описание, что именно там измеряется. Например, так:
Демонстрация: локальная функция sin работает в два раза быстрее, чем функция math.sin. Замедление происходит два раза: при извлечении поля math из таблицы глобальных переменных и при извлечении поля sin из таблицы math.
кусочек кода
Также можно привести ещё пример, демонстрирующий, что работа с глобальной переменной равносильна работе с полем таблицы.
А ещё важно продемонстрировать, начиная с какого числа использований становится выгодным копировать функцию math.sin в локальную переменную. Потому что если бездумно повторять советы из этого «урока», то вместо оптимизации может получиться пессимизация.
Также я советую для записи чисел с большим количеством нулей использовать научную форму. Чтобы понять, сколько нулей содержит число 100000, мне приходится задерживать взгляд на этом числе, а запись 1e5 считывается мгновенно.
-
3
-
-
30 минут назад, serafim сказал:ради интереса потыкал pairs и ipairs с пол сотни раз, всё норм порядок соблюдён
У меня тоже всегда соблюдалось, но документация не даёт гарантии, что так будет всегда.
31 минуту назад, serafim сказал:да это баг (сторон то 6), исправил уже после как статью выложил
Условие n==6 никогда не выполнится.
-
1
-
-
@serafim , меня смущает этот кусок кода:
print("пробный запуск") for i,n in pairs({3,2,4,5,0,1}) do red.setOutput(n, 15) if reactor.producesEnergy() then sideRed = n red.setOutput(sideRed, 0) print("реактор в стороне "..sideRed) os.sleep(1) break else red.setOutput(n, 0) end if n == 5 then print("\n".."реактор не запускается") os.exit() end end
Во-первых, непонятно, зачем перебирать элементы массива вместо простого цикла for i=0,5 do. Возможно, здесь важен порядок перебора, но итератор pairs не гарантирует нужного порядка. Но даже если в определённой версии Lua порядок соблюдается, то последние два элемента никогда не будут обработаны, потому что цикл оборвётся по условию n==5.
-
13 минуты назад, red2211 сказал:Понял, но не легче сделать как сделал я просто поделить текущее количество тепла на 100. Мы получаем то же значение что и при делении количество тепла в реакторе на теплоёмкость реактора но только на одну операцию меньше. Ведь так?
Так, если в описании программы будет сказано, что она не будет правильно работать при использовании обшивки реактора.
Обшивка реактора увеличивает теплоёмкость реактора. Поэтому при том же количестве тепла в реакторе его температура будет ниже. Но программа продолжит считать тепло вместо температуры.
-
1
-
-
15 минут назад, red2211 сказал:Если мы будем делить текущую теплоёмкость на максимальную то значения буду очень маленькие. К примеру сейчас теплоёмкость 4000, а макс 10000 то в нас получится 0,4. Думаю лучше оставить большые значения.
Не совсем так. Не текущая теплоёмкость, а текущее количество тепла getHeat(). А максимально возможное количество тепла getMaxHeat это и есть теплоёмкость реактора. Да, значения получаются маленькими в диапазоне от нуля до единицы включительно. Но если домножить на 100, то получим степень нагрева в процентах, если удобно работать с большими значениями.
15 минут назад, red2211 сказал:Не подскажете как реализовать что-то типу import в python, чтобы вынести все функции в отдельный файл?
В Lua для подключения библиотек используется функция require.
На форуме даже есть тема о создании библиотеки: Как создать библиотеку
-
1
-
-
9 часов назад, red2211 сказал:Рычаг нужен для запуска реактора если компьютер будет питаться от него. Иначе откуда компьютер возьмёт энергию если другого источника нету.
Да, в этой схеме нужен. Я невнимательно её рассмотрел. Привык к тому, что управляющий реактором компьютер питается от резервного энергохранителя на случай затухания реактора при нарушении поставок топлива.
Обнаружилась ошибка:
11 час назад, red2211 сказал:Когда температура реактора вернётся к допустимым значениям он опять включится.
Почитав код, я заметил, что на самом деле проверяется не температура реактора, а количество тепла в нём, что нарушает задуманную логику. Для получения именно температуры потребуется разделить количество тепла в реакторе на теплоёмкость реактора: T = reactor.getHeat()/reactor.getMaxHeat().
Также код программы содержит два идентичных куска, меняющих цвет части картинки, и кусок, бессмысленно перерисовывающий неизменную часть картинки:
while getHeat() >= 50 do gpu.setForeground(red) -- вывод фигуры треугольника ... gpu.setForeground(yellow) -- вывод фигуры огня и какой-то надписи ... computer.beep(500) os.sleep(1) gpu.setForeground(red) -- вывод фигуры огня и какой-то надписи ... computer.beep(500) os.sleep(1) end
Чтобы не дублировать код вывода фигуры огня, и не перерисовывать на каждой итерации цикле фигуру треугольника, можно использовать такой код:
gpu.setForeground(red) -- вывод фигуры треугольника ... local color = red while T >= 50 gpu.setForeground(color) -- вывод фигуры огня и какой-то надписи ... computer.beep(500) os.sleep(1) color = color==red and yellow or red end
А вообще, вывод крупных кусков неизменного текста я рекомендую вынести в отдельные функции. На работу программы это существенным образом не повлияет, но поможет облегчить основную часть кода, отвечающую за логику, что упростит поиск ошибок.
-
9 минут назад, red2211 сказал:Что требуется для роботы:
- ...
- Красный контроллер
10 минут назад, red2211 сказал:Планы на будущие:
- ...
- Добавить автоотключение реактора при выходе из програмы
Первым делом хорошо бы добавить автоотключение реактора при аварийном отключении компьютера, что на перегруженных серверах случается часто. При использовании красного контроллера это невозможно, т.к. он сохраняет своё состояние независимо от состояния компьютера. Другое дело, красная плата, вставленная в компьютер: сигнал на её выходе автоматически пропадает при отключении компьютера (не программы), благодаря чему отключается и реактор. Но для реализации такой схемы потребуется установить компьютер вплотную к реактору.
16 минут назад, red2211 сказал:Что требуется для роботы:
- ...
- Рычаг (для первого запуска реактора, затем надо выключить или сломать)
А рычаг-то зачем, если уже есть красный контроллер или красная плата, которые смогут осуществить не только все последующие запуски, но и первый тоже?
И зачем в коде везде используется string.format, даже там, где отсутствуют переменные, вывод которых требуется форматировать? Чем больше лишних действий делает программа, тем вероятнее этот компьютер отключится на перегруженном сервере. А если он не успеет к этому моменту отключить красный контроллер, то можно потерять и реактор и свой домик.
-
1
-
28 минут назад, Robo_start сказал:На данном сайте ещё есть поддержка мода ComputerCraft
Поддержка есть, т.к. многие помнят этот мод. Возможно, помнят не так хорошо, как OpenComputers, но помнят.
28 минут назад, Robo_start сказал:Я заметил что на этом сайте нету информации о моде ComputerCraft, но при этом сам Саит создан для мода ComputerCraft
Для новичков сильным преимуществом ComputerCraft является его простота. Почти все из нас начинали с него. Но более опытные программисты ищут разнообразия, простота мода становится скучной для них. Поэтому многие переходят на OpenComputers.
28 минут назад, Robo_start сказал:Вопрос о том что будет ли популярны программы для ComputerCraft
Компьютерные моды вообще не очень популярны в Майнкрафте. Тем не менее какая-то популярность имеется и у OpenComputers и у ComputerCraft.
-
1
-
-
2 минуты назад, Robo_start сказал:о командах оператора(админа) сервера
Тогда, как выше сказал @BrightYC , поможет отладочная плата. А её можно воткнуть и в робота тоже.
-
1 минуту назад, Robo_start сказал:Возможно ли исполнение команд из маинкрафт при помощи робота?
Каких именно команд?
С точки зрения программирования робот является компьютером, который имеет доступ к периферии робота. Логично, что робот может исполнять те же команды, что и компьютер.
-
-
1 минуту назад, kaka888 сказал:Хранить ли все приложения в одном репозитории, или для каждого приложения принято создавать отдельный? Если принято для каждого отдельный, то не утону ли я в этой куче репозиториев?
Принято делать так, как удобно автору приложений. Если приложение большое, то удобно создать для него отдельный репозиторий. Небольшие приложения, объединённые одной тематикой, бывает удобно хранить в одном репозитории. Это как с папками на компьютере. В одной папке можно хранить и сотню файлов. А иногда и ради трёх файлов удобнее создать отдельную папку.
5 минут назад, kaka888 сказал:Хочу перенести все свои разработанные под OpenComputers приложения (Lua, Python, SQL) на гитхаб, чтобы там хранились. Часть приложений планирую залить публично, остальное приватно.
Насколько я помню, приватные репозитории на гитхабе доступны лишь платно. Но существует, например, гитлаб, не имеющий такого ограничения.
-
2
-
-
5 минут назад, ECS сказал:А с точки зрения практичности для клана с десятком компьютеризированных электростанций/ферм в различных мирах централизованная и приватная схема надёжнее и быстрее. Имхо, пока не настанет всесерверная утопия, пока не передохнут диссиденты-дудосеры, игроки будут ориентироваться на локальные сети
Полностью согласен. Я сам на игровых серверах использую исключительно приватные сети, а широковещательные пакеты в беспроводных сетях посылаю только для аварийной коммуникации, когда секретность перестаёт быть приоритетной. Дудосеры вряд ли исчезнут, они тоже отыгрывают роль в игровом процессе, внося дополнительное разнообразие.
-
1
-
-
Архитектура этой сети похожа на упрощение OpenNet. В OpenNet также был слой на проводных платах и слой на связанных. И кроме этого имелся слой на беспроводных платах. В OpenNet, правда, использовались обычные компьютеры, а не серверы, поэтому система была более громоздкой.
-
15 минут назад, yurchik1 сказал:всё в порядке с другими большими ульями
Это очень странно выглядит. А если снести этот улей и построить заново, не помогает?
-
1
-
-
1 час назад, yurchik1 сказал:С другими ульями всё в порядке
Что значит другие ульи? Всё в порядке с другими большими ульями, или с ульями другого типа?

"Сворачивание" программы
в openOS
Опубликовано:
Это условности, что называть сервером, а что клиентом. В контексте твоего чата клиентская часть отвечает за взаимодействие с пользователем, а серверная должна принимать сообщения даже при отключенной клиентской части.