Очередь событий
- Войдите на сайт для отправки комментариев
Чт, 14/04/2016 - 22:53
Работа очереди организована по принципу FIFO (First In First Out) - первым пришел, первым ушел.
Предстовляет из себя массив
#define eventLenght 10//длина очереди событий byte eventList[eventLenght+1];//инициализация очереди событий + 1 пустое
Заполняется для начала нулями
for (int i=0; i <= 10; i++){ eventList[i]=0; }
Работа с очередью остоит из следующих функций
//взять задание byte getEvent(){//возвращает код задания из очереди return eventList[0]; } //сдвинуть очередь void pushEvent(){ for (int i=0; i <= eventLenght-1; i++){ eventList[i]=eventList[i+1]; } } //положить задание void cludEvent(byte e){ eventList[eventLenght-1]=e; }
Выполнение действий из очереди
if (getEvent()==0){//если нет действия
pushEvent();//сдвигаем очередь
}
else//иначе
{
run(getEvent());//выполнение действия согласно коду события
pushEvent();//сдвигаем очередь
}
Функция run(x) получает события из очереди и может выглядеть примерно так
//выполнить действие согласно таблице переходов void run(int f){ switch (f){ case 0: break; case 1: //одно действие break; case 3: //другое действие break; case 4: //третье действие break; } }
Пример использования
Если очень хочется писать свой велосипед, то есть смысл хотя бы посмотреть названия методов/функций в std::queue.
Заполняется для начала нулями
Зачем?
И вообще, прежде, чем выкладывать, Вы бы потестировали - там ошибок выше головы. Чуть-чуть пример не такой как у Вас и всё свалится.
Заполняется для начала нулями
Зачем?
Так у автора нуль в очереди означает нет события. Подход такой. Без хранения текущего индекса.
Вобще тема очереди событий не раскрыта. И дело не в ошибках, или подходах к реализации, а в назначении очереди событий.
Ведь именно она позволяет просто и понятно реализовать и меню многоуровневые и многозадачность. И при том стек не наращивать, и пиковую загрузку процессора размазывать.
У меня работает такое.
Обслуживание выборки команд и сдвига интегрированы в основной switch. Кстати разрабатывалось тоже при написании многоуровневого меню но на тачскрине.
Доработал очередь
Пример использования - пост #9
Добавил приоритет событий на выполнение
Рабочий пример использования - пост #14 (меню на LCDKeyPad Shield)
Очереди не делаются на сдвиге их в массиве туда-сюда. Создаётся переменные: указатель на голову и указатель на хвост, ими образуется кольцевая очередь. И ничего не требуется двигать, запонять нулями - использовать указатели намного эффективнее. К тому же в кольце и ФИФО, и ФИЛО реализубтся совершенно просто, в том числе и замещение данных при переполнении очереди. Приоретизация событий в очереди реализуется созданием очередей с различными приоритетами и выбором сначала очереди по приоритету, а затем из выбранной очереди уже собития по обычному порядку выборки. Точно таким же образом выполняется баласировка различных потоков событий.
Очереди не делаются на сдвиге их в массиве туда-сюда. ....
Спорный вопрос. Для короткой очереди 8-16 байт двигать будет быстрей чем два указателя проверять. И переполнение логичное, не влез последний - пролетел.
Приоретизация событий в очереди реализуется созданием очередей с различными приоритетами...
Согласен. Но для микроконтролера излишнее, если нужны разные приоритеты событий - скорей всего не то с архитектурой.
Очереди не делаются на сдвиге их в массиве туда-сюда. ....
Спорный вопрос. Для короткой очереди 8-16 байт двигать будет быстрей чем два указателя проверять. И переполнение логичное, не влез последний - пролетел.
Приоретизация событий в очереди реализуется созданием очередей с различными приоритетами...
Согласен. Но для микроконтролера излишнее, если нужны разные приоритеты событий - скорей всего не то с архитектурой.
Указатель может быть индексом в массиве. Чем его сложно проверять? Это не цепочка на указателях, как в больших процессорах, и не длинный указатель на адрес в памяти как в тех же процессорах больших. :) Преполнение одним сравнением проверяется, если перполнение с вытеснением, тоже запросто простым изменением двух переменных реализуется.
К слову, буффер кравиатуры в PC имеет всего 16 слов и он реализован именно на кольцевом списке, а там не просто адрес ячейки памяти как у АВРки, там надо загрузить в сегментный регистр сегмент данных БИОСа, взять адрес начала буфера из памяти, взять переменные хвоста, головы из длинны буфера из памяти.
Двигать массивы - это детский вариант, когда логика программирования ещё не усвоена. Или когда нет понимания, что программировать надо с самого начала красиво учиться, а не лепить глупые куски. :)
Про архитектуру не понял... Никто не мешает в АВР писать приложения событийно-ориентированные, а не прямой код. Мультизадачность и параллельное выполнение процесов, в т.ч. линейных, не подготовленных к мультизадачности, появилось задолго до появления процессоров с поддержкой переключения задач, называемых в РС протмод. На АВРке запросто можно сделать раздачу таймслотов.
И в чем он "спорный"? :)
"двигать очередь из 8-16 байт" .. это цикл из 8-16 чтений и 8-16 записей плюс инкремент одного-двух указателей (смотря на чем писано) плюс проверка на конец цикла. Итого имеем 4*(8-16) операций из которых 2 пары по 3 такта .. итого (2+2*3)(8-16) = 64/128 тактов МК. Плюсом это оформлено в ту или иную функцию, а стало быть расходы на её вызов/возврат - это ещё 9 тактов + по 2-6 тактов на каждый параметр (их 3: откуда, куда и сколько).
Переставить 2 указателя в коротком массиве (байтовых индекса) - это 2 байтовых операции, на которые МК как раз заточен и может делать 1-2 командами. В худшем случае это "считать байт - инкрементировать - записать" дважды. Итого .. 6 команд.
Ну вот как-то так выглядит ваше "быстрей" в чиселках ..
На АВРке запросто можно сделать раздачу таймслотов.
На станем больше ругаться, кто старое помянет...
Раздачу тайм-слотов - сделать будет не так просто, так как динамическая память очень мала, поэтому расходы тактов на сохранение контекста,и, ГЛАВНОЕ, расходы стека - недопустимы по размеру.
Но очень легко организовать не вытесняющую, а "добровольную" мультизадачность, как резиденты в ДОСе.
Поясню, если кто не помнит, что такое non preemtive multitasking, это когда не нужно переключать контекст и не нужно выделять тайм слоты. Корректность остается на ответственности программиста.
Технически, в терминах Ардуино это так, как будто у Вас не один loop(), а несколько. А в настоящем loop(), они просто, по очереди, вызываются. Если завис один из них - зависнет все. Вот тут можно добавить внешнее средство, которое такой "зависший" процесс выбросит из циклической очереди и вызовет "доктора", если программист предусмотрел обработку исключений. Я такое в далекой юности под ДОС для себя делал.
На АВРке запросто можно сделать раздачу таймслотов.
Можно, если больше на ней делать ничего не предполагается.
А вообще, можно-то можно, только вспомните Андрея Вознесенского:
«В час отлива, возле чайной
я лежал в ночи печальной,
говорил друзьям об Озе и величьи бытия,
но внезапно чёрный ворон
примешался к разговорам,
вспыхнув синими очами,
он спросил: … «А на фига?!»»
На АВРке запросто можно сделать раздачу таймслотов.
На станем больше ругаться, кто старое помянет...
Раздачу тайм-слотов - сделать будет не так просто, так как динамическая память очень мала, поэтому расходы тактов на сохранение контекста,и, ГЛАВНОЕ, расходы стека - недопустимы по размеру.
Но очень легко организовать не вытесняющую, а "добровольную" мультизадачность, как резиденты в ДОСе.
Поясню, если кто не помнит, что такое non preemtive multitasking, это когда не нужно переключать контекст и не нужно выделять тайм слоты. Корректность остается на ответственности программиста.
Технически, в терминах Ардуино это так, как будто у Вас не один loop(), а несколько. А в настоящем loop(), они просто, по очереди, вызываются. Если завис один из них - зависнет все. Вот тут можно добавить внешнее средство, которое такой "зависший" процесс выбросит из циклической очереди и вызовет "доктора", если программист предусмотрел обработку исключений. Я такое в далекой юности под ДОС для себя делал.
А ДОСе резидентя сидели на 9-м прерывании чаще всего и звали пока позовут, или на таймере чего-то там чикали. :) Теперь про АВР и его многозадачность. Стек тут совершенно не кусается. Если Вы когда-то в протмоде что-то писали, то прекрасно знаеете насколько несложная там идея и средства. Приминительно к АВР примерно так: на таймере при тике записываем все РОН в ячейку памяти для пограммы1, вынимаем из стека адрес прерваной команды и тоже сохраняем его, засовываем в стек адрес прерванной программы2, восстанавливаем РОН для программы 2, меняем влаг программ1-программа2 и вываливаемся из прерывания. Таким образом воможно выполнять парралельно две проги, совершеннно не знающих о соседях. Ну, естественно, порты, регистры...
На АВРке запросто можно сделать раздачу таймслотов.
Можно, если больше на ней делать ничего не предполагается.
А вообще, можно-то можно, только вспомните Андрея Вознесенского:
«В час отлива, возле чайной
я лежал в ночи печальной,
говорил друзьям об Озе и величьи бытия,
но внезапно чёрный ворон
примешался к разговорам,
вспыхнув синими очами,
он спросил: … «А на фига?!»»
Объясню нафига. Если Вы когда-то занимались производством или бизнесом, хотя бы, то должны понимать простую вещь: устелить деньгами заданную площадь легко, сократить затраты всегда сложнее. Иной раз может случиться так, что проц подходит по всем параметрам недорогой, но вот надо в нём парралельно выполнять процессы, или фоновое выпонение процесса иметь. Можно взять "Малину" или "Галилео", загрузить туда многозадасную ось и тащиться. Но! При серийном производстве стоимоть каждого экземпляра при этом увеличится, а стоимость однократных затрат на написание сложного кода аммортизируется т.с. на все выпускаемые экземпляры. Тут уже возникает вопрос оценки таких затрат в объёме производства. Мир потребления и развитие технологий замутил мозги, у нас неимоверные вычислительные возможности 99.9999% времени ждут нажатия кнопок мыши. :)
Фаэтон! Вот опять Вы возвращаетесь к тому, из-чего уже очень остро дикутировали, а именно спор ради сора, чтобы сказать последнее слово.
Ведь я же очень мягко и вежливо сказал, что при малом ОЗУ, а на контроллере его 1-2 килоБайта, вытесняющая многозадачность - невозможна. Так как каждый работающий процесс должен хранить весь контекст. Было бы 16К памяти - и я бы не стал ничего писать. Я понимаю, что Вы знаете про структуру процессора многое, но пишу про простую НЕХВАТКУ ПАМЯТИ.
Вы пишите РОН, а их 32 штуки, это 3% памяти! Хранить в контексте нужно не только РОН, но и програмные указатели и некоторые статусы.
Можно ли написать библиотеку для вытесняющей многозадачности на АВР? - конечно можно. Нужно ли? - конечно нет. Для такого маленького контроллера придется переработать алгоритм для использования в едином адресном пространстве в режиме "кооперативной многозадачности". Вот уже для Due (96К ОЗУ) - разумно писать если не "псевдо ОС", то библиотеку мультитрэдов уж точно.
Фаэтон! Вот опять Вы возвращаетесь к тому, из-чего уже очень остро дикутировали, а именно спор ради сора, чтобы сказать последнее слово.
Ведь я же очень мягко и вежливо сказал, что при малом ОЗУ, а на контроллере его 1-2 килоБайта, вытесняющая многозадачность - невозможна. Так как каждый работающий процесс должен хранить весь контекст. Было бы 16К памяти - и я бы не стал ничего писать. Я понимаю, что Вы знаете про структуру процессора многое, но пишу про простую НЕХВАТКУ ПАМЯТИ.
Вы пишите РОН, а их 32 штуки, это 3% памяти! Хранить в контексте нужно не только РОН, но и програмные указатели и некоторые статусы.
Можно ли написать библиотеку для вытесняющей многозадачности на АВР? - конечно можно. Нужно ли? - конечно нет. Для такого маленького контроллера придется переработать алгоритм для использования в едином адресном пространстве в режиме "кооперативной многозадачности". Вот уже для Due (96К ОЗУ) - разумно писать если не "псевдо ОС", то библиотеку мультитрэдов уж точно.
Погодите, речи не было о процессоре с 1-2 кБ. Может быть, в 2560 понадобится - оно же ведь тоже недорогое. :)
А вообще, я лишь объяснил смысл - может быть, кому-то пригоится. И вполне вероятную возможность подобной реалитзации. Лично я сам не стал с этим заморачиваться, хотя в разрабатываемом проекте процессору требуется очень много различных действий и вычислений делать. Сложу в стопочку. :)
Что такое программные указатели я не понял. Если адрес выполняемой команды, то он как раз через манипуляции со стеком и рулится. :)
Объясню нафига. Если Вы когда-то занимались производством или бизнесом, хотя бы, то должны понимать простую вещь:
Боюсь, что Вы этим занимались только теоретически или только на больших машинах.
Ваша таймслотная система сожрёт все ресурсы и больше туда ничего не влезет. Если мне нужно что-то делать параллельно, мои специалисты делают это аккуратно для конкретной задачи и в итоге умещаются в тиньки, куда Ваша система тайслотов даже голая не влезет.
Объясню нафига. Если Вы когда-то занимались производством или бизнесом, хотя бы, то должны понимать простую вещь: устелить деньгами заданную площадь легко, сократить затраты всегда сложнее. Иной раз может случиться так, что проц подходит по всем параметрам недорогой, но вот надо в нём парралельно выполнять процессы, или фоновое выпонение процесса иметь. Можно взять "Малину" или "Галилео", загрузить туда многозадасную ось и тащиться. Но! При серийном производстве стоимоть каждого экземпляра при этом увеличится, а стоимость однократных затрат на написание сложного кода аммортизируется т.с. на все выпускаемые экземпляры. Тут уже возникает вопрос оценки таких затрат в объёме производства. Мир потребления и развитие технологий замутил мозги, у нас неимоверные вычислительные возможности 99.9999% времени ждут нажатия кнопок мыши. :)
истиной многозадачности на AVR построить нельзя, псевдо (например на прерываниях) можно, и тут самый главный вопрос:
что такого происходит, что требует прерывания основной программы ???
единственно возможный ответ: Внешнее событие критическое по времени. (кнопка, датчик, сигнал).
собственно весь вопрос многозадачности для AVR - это вопрос обработки внешних событий, а что-бы у Вас не было заморочек - систему нужно грамотно проектировать, как по времени работы модулей так и по железу...
Если у Вас стоит проблемма многозадачности - значит Вы что-то не верно спроектировали изначально....
Если у Вас стоит проблемма многозадачности - значит Вы что-то не верно спроектировали изначально....
+плюсую+
ЗЫ: это не ГУИ, а контроллер. С такими ресурсами я не всегда согласен даже с использованием стиля ООП. Не говоря уже о многозадачности.
кстати простая самая реализация псевдо многозадачности:
за ножку 4 запускаем ШИМ, саму ножку 4 соединяем с ножкой 2 и подтягиваем к земле резистором 10к, на ножку 2 вешаем прерывание со своей функцией с несколькими флагами и одним делителем. в ней по при взведеном флаге его сбрасываем и запускаем нужную процедуру, внутри этой процедуры (последним оператор) взводим свой флаг заново...
получим равномерный запуск нескольких процедур, в каждой из которой можно обрабатывать внешние события вне зависимости от общей программы....
разумеется будет ограничение скорости ШИМ, но зато не нужно лезть глубоко :)
Парни, я не готов предъявить пример, когда требуется многозадачность кровь из носу. Ну, yапример, мне сейчас требуется получать и обрабатывать сложным вычислением массив информации, в это же время быть web-сервером, рисовать на экране. Меги то не только свотодиодиками моргают. Я сейчас пытаюсь избежать параллельности, контролировать приоритеты, вплодь до отказа в сервисе, если вычисление затянулось. Но избалаваность то есть, я же недавно в мегу пришёл. :)
Разумется речь не идёт о тинках. Я рассматриваю достаточно неплохие, недорогие и достаточно универсальные Mega2560/128 или STM32Fxxx.
кстати простая самая реализация псевдо многозадачности:
за ножку 4 запускаем ШИМ, саму ножку 4 соединяем с ножкой 2 и подтягиваем к земле резистором 10к, на ножку 2 вешаем прерывание со своей функцией с несколькими флагами и одним делителем. в ней по при взведеном флаге его сбрасываем и запускаем нужную процедуру, внутри этой процедуры (последним оператор) взводим свой флаг заново...
получим равномерный запуск нескольких процедур, в каждой из которой можно обрабатывать внешние события вне зависимости от общей программы....
разумеется будет ограничение скорости ШИМ, но зато не нужно лезть глубоко :)
Хорошая идея вытащить себя за волосы. :) Но зачем ноги путать, если прерывания можно генерировать таймером? :)
Парни, я не готов предъявить пример, когда требуется многозадачность кровь из носу. Ну, yапример, мне сейчас требуется получать и обрабатывать сложным вычислением массив информации, в это же время быть web-сервером, рисовать на экране. Меги то не только свотодиодиками моргают. Я сейчас пытаюсь избежать параллельности, контролировать приоритеты, вплодь до отказа в сервисе, если вычисление затянулось. Но избалаваность то есть, я же недавно в мегу пришёл. :)
Разумется речь не идёт о тинках. Я рассматриваю достаточно неплохие, недорогие и достаточно универсальные Mega2560/128 или STM32Fxxx.
ну не всегда хорошо иметь мегу, иногда два NANO лучше :), на одном веб на втором считай сложности...
имено об этом я и говорил, об изначально неверной архитектуре...
Но зачем ноги путать, если прерывания можно генерировать таймером? :)
дайте пример, но только такой, что-бы UART продолжал работать....
Многозадачность, вытесняющаяя .. корпоративная, тьфу ты .. кооперативная, можнаниззя, надонинада .. во развели байду!
Да нормально она РАБОТАЕТ на AVR. И даже 328p с его 2 килами пашет как миленький. В чем пгоблема-то?
Берем arhat.h, открываем файлик arhat.c и меняем режим компиляции с 2 на 3 .. и всё. Убрал "по умолчанию" по просьбе тех, кто этой библиотекой пользуется с той целью, для которой она и создавалась - "уменьшения размера скетчей" .. и ускорения их тоже.
В режиме "3" в обработчик таймера втыкается хук, который вызывается каждую миллисекунду .. вот вам и "второй процесс". И даже вовсе не обязательно, чтобы он успевал отрабатывать в эту же миллисекунду, хоть Serial.print() на 1200 гоняй. Обработчик его повторно не вызовет, тупо проигнорит до завершения.
Вам мало 2-х процессов? Окей. Заводим ещё один таймер или обработчик по ШИМ каналу или иной какой обработчик .. их в Меге аж 56 штук. "на выбор". :)
и никаких "специальных" действий не требуется.
Вам нужна "кооперативная многозадачность"? Да пожалуйста! everyMillis() в зубы, пардон руки .. :)
Парни, я не готов предъявить пример, когда требуется многозадачность кровь из носу. Ну, yапример, мне сейчас требуется получать и обрабатывать сложным вычислением массив информации, в это же время быть web-сервером, рисовать на экране. Меги то не только свотодиодиками моргают. Я сейчас пытаюсь избежать параллельности, контролировать приоритеты, вплодь до отказа в сервисе, если вычисление затянулось. Но избалаваность то есть, я же недавно в мегу пришёл. :)
Разумется речь не идёт о тинках. Я рассматриваю достаточно неплохие, недорогие и достаточно универсальные Mega2560/128 или STM32Fxxx.
ну не всегда хорошо иметь мегу, иногда два NANO лучше :), на одном веб на втором считай сложности...
имено об этом я и говорил, об изначально неверной архитектуре...
Мне нужен web-интерфейс, который просит достаточно много памяти, хотя и пишу его на голом javascript максимально компактно, возможно, даже запакую его содержимое. К тому же, сильно разочаровался в WizNet чипе со встроенным TCP - фигня крайне ненадёжеая, и придётся на мегу стек TCP вкорячивать программыный с модулем MAC уровня. В 328-ю мегу не влезит. Хотел вначале ставить один проц на обабутку, другой на интерфейс, но вопхнуть Мегу2560 ради редкого нужного web-интерфейса как-то не хочется, да и на первый - работяга проц на 328-й не тянет по причине недостаточности ног и, главное, внешних прерываний. Ставить 2 Меги2560 - уже излишне. Буду стараться уложить всё в одну мегу. Впрочем, пишу на Паскале, если не прокатит мега2560, зарулю всё в STM32. У меня ещё и атмеловкий кортекс какой-то валяется с PHY ethernet портом даже, пока даже не доставал из пакетика.
дайте пример, но только такой, что-бы UART продолжал работать....
я ни на что не намекаю, но таймеров несколько, на нанке - их 3 штуки, забрал таймер - лишился части ШИМ, тут уж - кому что! ;)
Зачем "лишился"? "перевернул и снова поиграл" .. тьфу-ты! Таймер по переполнению, ШИМ по своим регистрам .. одно другому даже в wiring не поме
Ну вот как-то так выглядит ваше "быстрей" в чиселках ..
Это в Вашем недалеком мозгу так выглядит. Иначе бы подумали, что в кольцевом буфере есть две особые ситуации - указатель "головы" догнал хвост и инкремент указателя достиг конца буфера и необходимо вернутся к началу. И их необходимо контролировать не только при извлечении но и при добавлении.
Код без кольца и с кольцевым буфером.
Дизассемблер
Линейный буфер со сдвигом 8dc-90e т.е. 50 команд. Плюс 6 команд на каждую не пустую позицию в буфере после извлечения. По максимуму 7 сдвигов.
Цикличный 920-97e 94 команды. Минус чегото там при недостижении на текущем цикле границы буфера.
Хотите точнеё - считайте сами, я Вас уже учил как это делается, Вы должны помнить ещё.
А для меня видно, что однозначного преимущества нет. При коротком буфере явно предпочтительней сдвиг, при длинном циклический буфер. Очевидно если только меню делается то сдвиг лучше. Если вся система - нужно подробней смотреть.
ПС. Код написан просто для иллюстрации подходов, в проекте не испытан, требует отладки. Я пользую шаблоны из своего сообщения выше, устраивают, требования к скорости к ним не выдвигалось.
:) Вы сделали мой вечер. Всегда утверждал, что наговнокодить много чего можно. Вы - постарались. :)
Да, и ваш "ассемблер" не соответствует коду. В нем с пропущены операции инкремента-декремента указателя "pK" .. в силу оптимизации инлайн подстановки функций работы с буфером. Так что .. продолжайте учиться считать правильно. Предыдущий урок вам ни разу не помог, как видно.
Как я вам и написал, ваш ассемблер вам показал верно: строки с 904 по 90e: имеем 2 команды по 3 такта + 3 команды по 1 такту + 1 по 2 такта .. итого на итерацию цикла имеем 2*3+3*1+1*2 = 6+3+2 = 11 тактов, что для буфера в 8-16 байт даст .. 88..176 тактов. только сдвиг буфера. Я ещё вам "оптимальную оценку дал в 64 такта! :)
В цикличном буфере на индексах массива - считать шибко не буду, поверю вашему коду .. пусть будет 94 команды. Хотя у вас там явная описка
if(bK==8)
{
pK=0;
}
надо было bk=0 .. Упс, -1 команда, ну да фиг с ней. Пример все одно крив как турецкая сабля в силу ущемленного ЧСВ. :)
А самое главное, что ваш ассемблер ВАМ НАГЛЯДНО показал, что в этих 94 командах ровно 4 полезных поерации с памятью .. что я вам и написал "примерно".
Итого, даже ваш ассемблер вам показывает, даже на вашем кривом примере, что код на индексах массива в 8-16 байт - или такой же или КОРОЧЕ И БЫСТРЕЕ.
Продолжайте садиться в лужу дальше.
904: 82 91 ld r24, -Z
??? "-Z" Снова GCC кривой?! Или Вы слепой?
В цикличном буфере на индексах массива - считать шибко не буду, поверю вашему коду .. пусть будет 94 команды.
Такты с командами сравниваете?! Клоун! Взялись считать такты - считайте оба варианта и сравнивайте тогда. Или команды с командами (что не очень точно) или такты но с тактами!! Не надейтесь, здесь не все дурные.
Принимается. Описка. Один такт минус. Только минусовать пока не от чего, Вы такты для циклического так и не шмогли посчитать.
Гыыы!! У нас теперь операции (я так перевел "поерации") процессора делятся на полезные с памятью и безполезные, или может прости господи вредные. И безполезные можна вычеркнуть из загрузки процессора? Вы точно клоун!
Ну вот выложили Вы код который "должно быть чуток поменьше". Сами понятно дизасемблер не глянули. Ну на шо Вы расчитывали? Что мне сложно будеь? Так таки нет.
Те же 6 команд цикла. И по тактам похоже один в один выходит. Нафига Вы это публиковали не проверив?
Мне нужен web-интерфейс, который просит достаточно много памяти, хотя и пишу его на голом javascript
Это сильно!
Logik пререстаньте уже нести чушь и опровергать очевидные вещи. :) Двигать кусок памяти менее эфективно, нежели указатели, если кусок памяти более размера указателей. У аж что там за хрень, простите, с указателями в курицалапой написанном исходнике прммера для демонстрации асм кода...
Мне нужен web-интерфейс, который просит достаточно много памяти, хотя и пишу его на голом javascript
Это сильно!
А чего издеваетесь? Web - это такое дерьмо с точки зрения программирования, настолько всю глючно, неочевидно, нелогично, через задницу... Полдня бился, выясняя почему willValidate всегда даёт false, а checkValidity() всегда даёт true, пока не обнаружил, что оно так для disabled полей, которые уже успел до проверки погасить, всегда дает успешную проверку. Но это, логично, а вот т.с. кросбраузерность - это вообще катастрофа - кто и как код воспринимает. Жуть! Вот пример: объявляем input как нумбер, даём патерн даже "только цифры" - в хроме всё замечательно: патерно пускает вводить только цифры, а эксплорер, если введена первой цифра, уже и буковки следом запросто пускает. Самое прикольное тип инпута поменять на текст и всё правильно работает. Жуть! :)
Простите, отвлёкся - настолько заканало оно. :)
Logik пререстаньте уже нести чушь и опровергать очевидные вещи. :) Двигать кусок памяти менее эфективно, нежели указатели, если кусок памяти более размера указателей. У аж что там за хрень, простите, с указателями в курицалапой написанном исходнике прммера для демонстрации асм кода...
Указатели требуют дополнителных операций проверки. И их размерность превышает разрядность процессора, потому эффективность падает. Знаеш чем полуучка хуже неука? Знанием своим и увереностю в его полноте. Сразу проверьте, попробуйте, а потом советы давайте по теме. Напишите лучше, покажите код эффективне, тогда и поговорим, а то писаболов тут хватает.
Logik пререстаньте уже нести чушь и опровергать очевидные вещи. :) Двигать кусок памяти менее эфективно, нежели указатели, если кусок памяти более размера указателей. У аж что там за хрень, простите, с указателями в курицалапой написанном исходнике прммера для демонстрации асм кода...
Указатели требуют дополнителных операций проверки. И их размерность превышает разрядность процессора, потому эффективность падает. Знаеш чем полуучка хуже неука? Знанием своим и увереностю в его полноте. Сразу проверьте, попробуйте, а потом советы давайте по теме. Напишите лучше, покажите код эффективне, тогда и поговорим, а то писаболов тут хватает.
Трандец! Даже не пойму недоучка ты, полуучка или просто по-бабски побазарить любитель...
Ещё раз для размышления: указатели на голову и хвост очереди могут и чаще всего бывают не адресными указателями на ячейку памяти, а индексами массива. Ибо очереди не только из байтов случаются и расчёт смещения люди отдают компилятору.
byte head, tail = 0;
А гон про личные мои качества и участие в обсуждениях, в коих ты не менее свой нос суёшь, не имея понятия о теории, нахватавшись кусков, вываливая говнокод, не заморачиваясь хорошим тоном, что свойственно челу, пишущему на коленках и никогда не работавшему в серьёзном проекте, мне совершенно по-барабану. :))) И я уже просил тебя и ещё одну баразную бабу избавить меня от вашего внимания. :)
faeton, писал: "Двигать кусок памяти менее эфективно, нежели указатели, если кусок памяти более размера указателей."
Верно, что я и пытался объяснить. Индексирование кольцевого буфера на массиве требует проверки для каждого индекса (головы и хвоста): выход за конец массива - "закольцовка" и "догон друг друга", чтобы голова не обогнала хвост и наоборот. То есть имеем 2*2 = 4 проверки. Да, их надо делать и при вставке и при извлечении из очереди. Итого 8 проверок. Для байтового индекса (буфер до 256 элементов) имеем короткие регистровые операции, вместо составных.
Для буфера "со сдвигом" элементов проверки выхода за границу массива - тоже необходимы. И точно также И на вставке И на удалении элементов. Тут, наверное, указатель тоже правильней делать индексом массива, а не как показано в говно-примере, ибо он становится байтовым. Но не уверен, надо смотреть. Лично мне - нафиг не надо (потому и не проверяю, ибо вполне достаточно оценочного анализа), ибо предпочитаю код не требующий буферизаций от слова "вовсе" - затратно оно "буферизация" и тормозит нещадно в целом, а для МК - это может ещё и быть критичным.
Далее. Буфер со сдвигом гарантировано требует переноса данных, и каждая операция переноса требует ЧТЕНИЯ из памяти и ЗАПИСИ в неё, элемента данных буфера (хотя бы 1 байта). [Такие операции у Атмела выполняются ЗА 3 ТАКТА каждая, о чем хорошо написано в даташитах (не все читают)] Исправлено: Операции чтения-записи исполняются нормально за 2 такта, соответственно ниже пересчитано тоже[]. Плюсом требуется посчитать и проверить счетчик переноса .. что ещё добавляет 1 операцию (посчитать) и 1 проверку и ветвление (переход - 2 такта!). То есть имеем гарантированные 5 операций на элемент переноса. Итого имеем 2+2+1+2 = 7 тактов на каждый байт переноса. Для более сложных элементов буферизации - тут все существенно усложняется.
Итого, в сравнении у нас остается 6 проверок (посчитать и перейти = по 3 такта = 18 тактов) против переноса данных (по 9 тактов на элемент).
Отсюда вывод: буфер со сдвигом становится эквивалентен буферу на индексах "голова","хвост" при его размере .. 2-3 байта. Что [практически] полностью совпадает с утверждением, цитированным выше:
"Двигать кусок памяти менее эфективно, нежели указатели, если кусок памяти более размера указателей."
Оно конечно же очевидное, как и предыдущий урок по обработчику TWI (I2C):
"Всякий неблокирующий код предпочтительнее любого блокирующего и, тем более, при равных или похожих затратах на время и место"
Но .. видимо не для каждого. :)
А главное в том, что кольцевой буфер на массиве с головой и хвостом - совершенно НЕ ЗАВИСИТ от размеров как самого буфера так и размеров хранящихся в нем данных .. ну почти не зависит. В то время как сдвиговый буфер линейно ухудшает время исполнения КАК от размера буфера, ТАК И от размера хранящихся в нем данных.
:)
Те же 6 команд цикла. И по тактам похоже один в один выходит. Нафига Вы это публиковали не проверив?
Конечно не глядел, оно мне - зачем? :)
Я бы развернул этот кусок так:
Кстати, странно, но ваш ассемблер инкрементирует по 2 байта, как будто вы смещаете слова, а не байты .. сами писали? :)
Надеюсь, читателям будет полезно объяснение невежде пагубности таскания содержимого массивов. :) Их не двигают даже в тех процессорах, где есть инструкции строкового перемещения. Гениальные выскочки, безусловно, не раз перворачивали Мир, но не в этом случае. :)
Надеюсь, читателям будет полезно объяснение невежде
Читатели уже весь попкорн съели, наблюдая эпичный фаллометрический срач трёх невежд.
И не говорите .. пошел за попкорном. :)
Надеюсь, читателям будет полезно объяснение невежде
Ну, у кого организм только попкорн поглощать умеет, жорошо бы и к горшку быть приученым, а не гадить тут с очередным бестолковым замечанием... :))))
Ну, у кого организм только попкорн поглощать умеет, жорошо бы и к горшку быть приученым, а не гадить тут с очередным бестолковым замечанием... :))))
Эк тебя понесло то! Аж о горшке вспомнил? А чего так? Сам же к читателю взывал! Пока не взывал я помалкивал.
Никак не понравилась реакция читателя? Ну так ты мил человек привыкай. Мы читатели - народец по большей части низкий и неблагодарный. Не ценим снисходящих до нас гениев. Дермецо народец, но уж такие мы. Другими господь не создал. Не обессудь, барин.
Вот жеж .. а я уже половину попкорна сожрал, ожидая не менее фаллометрическое разъяснение "вежды" Ворона, кто же тут таки не прав оказывается .. так будет разъяснение, барин? Пардон, "читатель"? Или стоит податься к Logik-у в ученики говнокодерства? Уж вразуми, не откажи.. (попкорн кончается) :)
Ты Архатыч, меня с фаэтоном и логиком не путай. Это вы трое - любители свою безграмотность напоказ выставлять, а я не писатель, я - читатель. Я своё невежество при себе держу, авось никто не заметит.
А-а-а .. (подавился попкорном) .. так значит не будет никого просветлению какая буферизация православна, так? Абыдна гавариш.
А может и взаправду нифига не рубишь, а так, дерьмеца на вентилятор пришел подкинуть " по привычке" .. в общем - пофиг. Попкорн я уже съел.
И Логик чего-то притих, паразит... :) Выходи - мириться будем и по чистоте душевной плохого не вспомним. :)
Те же 6 команд цикла. И по тактам похоже один в один выходит. Нафига Вы это публиковали не проверив?
Конечно не глядел, оно мне - зачем? :)
Я бы развернул этот кусок так:
Кстати, странно, но ваш ассемблер инкрементирует по 2 байта, как будто вы смещаете слова, а не байты .. сами писали? :)
Ржака. Уже компилирует вручную )))) Правда с коментариями "точно не помню".
А почему инкремент по 2 байта?! Так смотрите свой код из http://arduino.ru/forum/programmirovanie/ochered-sobytii#comment-188824 даже не поленюсь его сюда скопировать.
У Вас tmp инкрементируктся 2 раза. В операторе цикла и в его единственной строке. Что написали - то и скомпилилось))) Как Вы это называете - гомнокодер. В двух строках простейших. И ещё и сообщение накропали "А почему инкремент по 2 байта?!" ))))) А потому что у автора ошибка генетическая.
ПС. Шо это за RJMP за цыкл на 8d8 ?! Это наверно не полезные команды, их не выполнять )))
И Логик чего-то притих, паразит... :) Выходи - мириться будем и по чистоте душевной плохого не вспомним. :)
От паразита слышу :) Я не подряжался Вас мокать по выходным. Есть и интересней дела. Могу по будням и под настроение. А если скучаете, ну за скромное денежное вознаграждение могу и по выходным. Но по праздникам - не расчитуйте.
По существу- так и нечего коментировать у Вас, Вы же ничё и не написали по теме. Ну я Вам ща вброшу для поддержания темы.
Вобще затраты производительности процессора на обслуживание очереди сообщений для менюшек правильно расчитывать для пустой очереди, именно пустые её проходы составляют более 99% и следовательно, ни её длина ни скорость работы полной особой роли не играют. Согласны? ;)