| Форум РадиоКот https://radiokot.ru/forum/ |
|
| Как оптимизировать использование функций? https://radiokot.ru/forum/viewtopic.php?f=57&t=182161 |
Страница 1 из 4 |
| Автор: | Land [ Пт апр 08, 2022 11:28:52 ] |
| Заголовок сообщения: | Как оптимизировать использование функций? |
Собственно говоря, в проекте есть функции вида: Код: /** выбор меню числа месяца */ static void day_of_month_Select(void) { //ds3231_read_data(data);// Вывести дату dsprintf(string, "%i/%i/20%02i", data[1], data[2], data[3]); lcd_gotoxy(0,1); lcd_str_out(string); x = data[1]; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; if(x > 31) x = 1; else; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 1) x = 31; else; } else; dsprintf(string, "%i/%i/20%02i", x, data[2], data[3]); lcd_gotoxy(0,1); lcd_str_out(string); } data[1] = x; } /** выбор меню месяца */ static void month_Select(void) { dsprintf(string, "%i/%i/20%02i", data[1], data[2], data[3]); lcd_gotoxy(0,1); lcd_str_out(string); x = data[2]; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; if(x > 12) x = 1; else; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 1) x = 12; else; } else; dsprintf(string, "%i/%i/20%02i", data[1], x, data[3]); lcd_gotoxy(0,1); lcd_str_out(string); } data[2] = x; } Очевидно, что по своей сути они выполняют одну и ту же операцию, но над разными данными и с разными граничными критериями. Плюс изменяется место вывода меняемой переменной в строке. Плюс, есть группа таких же функций, но выводящих в строке не три, а два параметра. То, как выводятся данные на экран меню и изменяется переменная, меня полностью устраивает. Не устраивает необходимость фактического дублирования одного и того же кода десяток раз (не впихивается на кристалл Каков может быть путь оптимизации подобной реализации? Надо оптимизировать по размеру прошивки. |
|
| Автор: | veso74 [ Пт апр 08, 2022 11:53:42 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
1. В функции используете глобальные переменные. На самом деле у Вас это не функция, а, например. ответвления основной программы (например, для более простых действия). Используйте локальные, которые после ухода, память под них освободится. 2. Я бы использовал повторяющийся фрагмент кода для обеих функций и входных переменных: например. с ключом действия (bool, или uint8_t, если много), который будет отправлен в зависимости от того, что обрабатываете (в случая: day_of_month_Select или month_Select). 3. На C выход из цикла через break не "самый красивый". Попробуйте написать по другому. 4. "Медленные" операции (как lcd_gotoxy(), lcd_str_out() я бы провернул в конце функции, даже в теле программы. Сначала: обработка данных, присвоение в новой переменной , напр. что будет напечатано. Наконец: LCD-печать. |
|
| Автор: | Land [ Пт апр 08, 2022 12:03:48 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
1. В функции используете глобальные переменные. На самом деле у Вас это не функция, а, например. ответвления основной программы (например, для более простых действия). Используйте локальные, которые после ухода, память под них освободится. 2. Я бы использовал повторяющийся фрагмент кода для обеих функций и входных переменных: например. с ключом действия (бул.), который будет отправлен в зависимости от того, что обрабатываете. 3. На C выход цикла/функции через break не "самый красивый". Попробуйте написать по другому. 4. "Медленные" операции (как print) я бы провернул в конце. Сначала: обработка данных, присвоение, напр. что будет напечатано и значения: присвоить новой переменной печати. Наконец: LCD-печать. 1.Переменные на самом деле глобальные. После модификации они используются в основном теле программы для вывода на меню. Локальная одна - х. 3. не самый красивый. 4. Мне ж надо видеть изменение переменной в реальном времени, не вслепую же тыкать. 2. Спасибо, попробую. ЗЫ. У меня проблема сейчас в размере кода, не в быстродействии. Мне надо урезать около 1.5 кБ. |
|
| Автор: | veso74 [ Пт апр 08, 2022 12:08:47 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
Цитата: 1.Переменные на самом деле глобальные. Примерно x вообще не глобальная переменная. -- Да, Вы написали. -- У Вас есть повторяющийся фрагмент. Особенно со стрингами. |
|
| Автор: | OKF [ Пт апр 08, 2022 12:32:13 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
ТС должен был изначально сказать в чём должна быть оптимизация... В объёме кода, в скорости, в размере исходника... в чём? |
|
| Автор: | Land [ Пт апр 08, 2022 12:41:50 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
[quote] У Вас есть повторяющийся фрагмент. Особенно со стрингами. да. У меня есть повторяющийся фрагмент. но ведь Код: dsprintf(string, "%i/%i/20%02i", data[1], data[2], x); lcd_gotoxy(0,1); lcd_str_out(string); это все равно вызовы функций. И если я их всуну в одну функцию и буду ее вызывать, размер кода ведь не уменьшится? Или я не правильно понимаю? Добавлено after 6 minutes 17 seconds: ТС должен был изначально сказать в чём должна быть оптимизация... В объёме кода, в скорости, в размере исходника... в чём? Сорян. Думал фразы "Не устраивает необходимость фактического дублирования одного и того же кода десяток раз (не впихивается на кристалл |
|
| Автор: | Jack_A [ Пт апр 08, 2022 12:46:14 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
Мне надо урезать около 1.5 кБ. Радикальный и надёжный совет - написать на асме - я так понимаю, мимо кассы ? Вообще применение функций оправдано, если только много раз повторяется длинная последовательность операторов, и её "не-дублирование" минус затраты на вход в процедуру и выход из неё ( с учётом сохранения регистров, передачи параметров) даёт уменьшение размера кода. Помогает также замена библиотечных функций ввиду их избыточности вследствие многовариантности - собственными, расчитанными на конкретный вариант *. Советы банальны до неприличия, но всякая истина банальна. ---------- * Предвижу реплику оппонента: "А если в дальнейшем оно потребуется при модернизации?" Ответ: всё предвидеть не мог даже Нострдамус. Тогда возьмём камень "потолще" . |
|
| Автор: | veso74 [ Пт апр 08, 2022 12:54:07 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
Перейти от простого к сложному: компилятор? Настроен он для оптимизации? (по объем памяти), уровень оптимизации? Некоторые оптимизаторы "творят чудеса" (а некоторым: приходится явно давать им указания). Поддерживаю сообщение выше о Нострадамусе И попробуйте много варианты. Только Вы знаете, что с код происходит. |
|
| Автор: | Land [ Пт апр 08, 2022 13:25:07 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
Jack_A, asm не вариант из-за трудоемкости. Я знаю, что пишут и пишут бОльшие проекты, но в моем случае оно того не стоит. veso74, AVR/GNU C Compiler оптимизация по размеру -Os А какой больше информации надо? ну вот здесь все 12 реализаций функции. Тело функции одно, изменяется лишь параметр, который изменяется, границы его изменения, да формат вывода строки с результатом. СпойлерКод: /** выбор меню числа месяца */ static void day_of_month_Select(void) { signed char x = 1; dsprintf(string, "%i/%i/20%02i", data[1], data[2], data[3]); lcd_gotoxy(0,1); lcd_str_out(string); x = data[1]; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; if(x > 31) x = 1; else; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 1) x = 31; else; } else; dsprintf(string, "%i/%i/20%02i", x, data[2], data[3]); lcd_gotoxy(0,1); lcd_str_out(string); } data[1] = x; } /** выбор меню месяца */ static void month_Select(void) { signed char x = 1; dsprintf(string, "%i/%i/20%02i", data[1], data[2], data[3]); lcd_gotoxy(0,1); lcd_str_out(string); x = data[2]; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; if(x > 12) x = 1; else; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 1) x = 12; else; } else; dsprintf(string, "%i/%i/20%02i", data[1], x, data[3]); lcd_gotoxy(0,1); lcd_str_out(string); } data[2] = x; } /** выбор меню год */ static void year_Select(void) { //ds3231_read_data(data);// Вывести дату dsprintf(string, "%i/%i/20%02i", data[1], data[2], data[3]); lcd_gotoxy(0,1); lcd_str_out(string); signed char x = 1; //lcd_init(1); x = data[3]; //BUTTON = BUTTON_NONE; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 22) x = 22; else; } else; dsprintf(string, "%i/%i/20%02i", data[1], data[2], x); lcd_gotoxy(0,1); lcd_str_out(string); } data[3] = x; } /** выбор меню дня недели */ static void day_Select(void) { signed char x = 1; dsprintf(string, "%i", data[0]); lcd_gotoxy(0,1); lcd_str_out(string); //lcd_gotoxy(1,2); //lcd_init(1); x = data[0]; //BUTTON = BUTTON_NONE; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; if(x > 7) x = 1; else; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 1) x = 7; else; } else; dsprintf(string, "%i", x); lcd_gotoxy(0,1); lcd_str_out(string); } data[0] = x; } /** выбор меню часа */ static void hours_Select(void) { signed char x = 1; ds3231_read_time(time); // Вывести время dsprintf(string, "%02i:%02i:%02i", time[0], time[1], time[2]); lcd_gotoxy(0,1); lcd_str_out(string); //lcd_gotoxy(1,2); //lcd_init(1); x = time[0]; //BUTTON = BUTTON_NONE; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; if(x > 23) x = 0; else; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 0) x = 23; else; } else; dsprintf(string, "%02i:%02i:%02i", x, time[1], time[2]); lcd_gotoxy(0,1); lcd_str_out(string); } time[0] = x; } /** выбор меню минут */ static void minutes_Select(void) { signed char x = 1; // Вывести время dsprintf(string, "%02i:%02i:%02i", time[0], time[1], time[2]); lcd_gotoxy(0,1); lcd_str_out(string); //lcd_gotoxy(1,2); //lcd_init(1); x = time[1]; //BUTTON = BUTTON_NONE; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; if(x > 59) x = 0; else; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 0) x = 59; else; } else; dsprintf(string, "%02i:%02i:%02i", time[0], x, time[2]); lcd_gotoxy(0,1); lcd_str_out(string); } time[1] = x; } /** изменение часа открытия */ static void open_hours_Select(void) { dsprintf(string, "%02i:%02i", set_HOUR_OPEN, set_MINUTE_OPEN); lcd_gotoxy(0,1); lcd_str_out(string); signed char x = 1; //lcd_init(1); x = set_HOUR_OPEN; //BUTTON = BUTTON_NONE; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; if(x > 23) x = 0; else; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 0) x = 23; else; } else; dsprintf(string, "%02i:%02i", x, set_MINUTE_OPEN); lcd_gotoxy(0,1); lcd_str_out(string); } set_HOUR_OPEN = x; } /** изменение минут открытия */ static void open_minutes_Select(void) { dsprintf(string, "%02i:%02i", set_HOUR_OPEN, set_MINUTE_OPEN); lcd_gotoxy(0,1); lcd_str_out(string); signed char x = 1; //lcd_init(1); x = set_MINUTE_OPEN; //BUTTON = BUTTON_NONE; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; if(x > 59) x = 0; else; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 0) x = 59; else; } else; dsprintf(string, "%02i:%02i", set_HOUR_OPEN, x); lcd_gotoxy(0,1); lcd_str_out(string); } set_MINUTE_OPEN = x; } /** изменение часа зактытия */ static void close_hours_Select(void) { dsprintf(string, "%02i:%02i", set_HOUR_CLOSED, set_MINUTE_CLOSED); lcd_gotoxy(0,1); lcd_str_out(string); signed char x = 1; //lcd_init(1); x = set_HOUR_CLOSED; //BUTTON = BUTTON_NONE; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; if(x > 23) x = 0; else; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 0) x = 23; else; } else; dsprintf(string, "%02i:%02i", x, set_MINUTE_CLOSED); lcd_gotoxy(0,1); lcd_str_out(string); } set_HOUR_CLOSED = x; } /** выбор меню минут закрытия */ static void close_minutes_Select(void) { dsprintf(string, "%02i:%02i", set_HOUR_OPEN, set_MINUTE_OPEN); lcd_gotoxy(0,1); lcd_str_out(string); signed char x = 1; //lcd_init(1); x = set_MINUTE_CLOSED; //BUTTON = BUTTON_NONE; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++x; if(x > 59) x = 0; else; } else; if(BUTTON == BUTTON_DOWN) { --x; if(x < 0) x = 59; else; } else; dsprintf(string, "%02i:%02i", set_HOUR_CLOSED, x); lcd_gotoxy(0,1); lcd_str_out(string); } set_MINUTE_CLOSED = x; } /** выбор меню изменения порога температуры */ static void degress_Select(void) { set_TEMPR = temperatura; // Вывести температуру dsprintf(string, "%3i", set_TEMPR); lcd_gotoxy(0,1); lcd_str_out(string); //lcd_gotoxy(1,2); //lcd_init(1); //BUTTON = BUTTON_NONE; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++set_TEMPR; if(set_TEMPR > 59) set_TEMPR = 20; else; } else; if(BUTTON == BUTTON_DOWN) { --set_TEMPR; if(set_TEMPR < 20) set_TEMPR = 59; else; } else; dsprintf(string, "%3i", set_TEMPR); lcd_gotoxy(0,1); lcd_str_out(string); } } /** выбор меню изменения порога яркости */ static void brightnes_Select(void) { dsprintf(string, "%3i", level_BRIGHTNES); lcd_gotoxy(0,1); lcd_str_out(string); //lcd_gotoxy(1,2); //lcd_init(1); set_BRIGHTNES= level_BRIGHTNES; //BUTTON = BUTTON_NONE; while(1) { skan_key(); if((BUTTON == BUTTON_LEFT)||(BUTTON == BUTTON_RIGHT)) break; else; if(BUTTON == BUTTON_UP) { ++set_BRIGHTNES; if(set_BRIGHTNES > 255) set_BRIGHTNES = 1; else; } else; if(BUTTON == BUTTON_DOWN) { --set_BRIGHTNES; if(set_BRIGHTNES < 0) set_BRIGHTNES = 255; else; } else; dsprintf(string, "%3i", set_BRIGHTNES); lcd_gotoxy(0,1); lcd_str_out(string); } } |
|
| Автор: | veso74 [ Пт апр 08, 2022 13:33:53 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
Код: if (BUTTON == BUTTON_UP) { ++set_TEMPR; if (set_TEMPR > 59) set_TEMPR = 20; else; } else; Если условие по else нет, то удалите. Так с действие ";" как это интерпретировать? Что-то удаляли? Что-то дополните в будушем там? В ето else также не вижу смисл: Код: if ((BUTTON == BUTTON_LEFT) || (BUTTON == BUTTON_RIGHT)) break; else; Если условие выполнено, то выйти из цикла, если нет, то продолжаем (ничего не делать и вращаться в цикле). Ето else как код, оставшийся от предыдущей программы ... --- Вероятно и BUTTON можно сделать локальная - после выхода из меню она больше не нужна (до следующего нажатия)? ... Я думаю, что и string не нужнапосле выхода из текущего действия (можно сделать локальная)? |
|
| Автор: | Jack_A [ Пт апр 08, 2022 14:16:37 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
Если условие по else нет, то удалите. Думаю, компилятор сам это сделает. Хотя полную уверенность можно получить, посмотрев листинг с раскрытыми командами. Я Си в МК не применял, поэтому - такое в листинге можно посмотреть? |
|
| Автор: | veso74 [ Пт апр 08, 2022 14:19:14 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
Ето, вероятно, не произойдет с мышлением :/. Пробуйте, сравнивайте, тестируйте. Хотите идеи, мы даем идеи, делитесь результатом. Дело в 10 секунд. Другого пути нет. (частично пользуюсь переводчиком БГ -> РУ) |
|
| Автор: | Land [ Пт апр 08, 2022 14:20:26 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
veso74, убрал. Парадокс, но размер кода был 9276. Стал 9286. мне эти else; дают чисто лучшую читаемость кода, не запутываюсь |
|
| Автор: | OKF [ Пт апр 08, 2022 14:55:51 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
Land, основная идея в том что бы исходный код был читаемый, понимаемый. Т.е., "оптимизацией" нужно заниматься уже в последнюю очередь. И то, зачастую это лишнее! Ибо компиляторы сейчас продвинутые и результирующий код выдают не хуже вашего ассемблера. |
|
| Автор: | veso74 [ Пт апр 08, 2022 14:57:09 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
За кнопкам думаю правильнее проверять if с выключением: после нажатия выполняется только одна функция. Код: if (condition_1) { } else if (condition_2) { } else if (condition_3) { } и бы расставил приоритеты, т.е. выход: наконец. Код: else if ((BUTTON == BUTTON_LEFT) || (BUTTON == BUTTON_RIGHT)) ... Даже в некоторых случаях логически эта проверка не нужна (если у Вас есть индикация: какая-то кнопка активирована). |
|
| Автор: | Land [ Пт апр 08, 2022 15:02:50 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
Как передать в функцию формат строки? вот есть dsprintf(string, "%i/%i/20%02i", data[1], data[2], data[3]); где "%i/%i/20%02i" -- это формат вывода строки. Как его заменить переменной, которую можно было бы передать функции при ее вызове? что-то вроде format = "%i/%i/20%02i", а затем вызов функции ыigned char settinng_par (format, char min_x, char max_x, signed char x, signed char y, signed char z ) и потом это получается в виде dsprintf(string, format, x, y, z); ? |
|
| Автор: | veso74 [ Пт апр 08, 2022 15:06:38 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
В PIC есть char *str. В Arduino есть и String (String class). Вероятно в Вашем случае char *str достаточно. Код: void LCD_print(char *str) {
while(*str) LCD_out(*str++); } ... LCD_print("test"); |
|
| Автор: | Land [ Пт апр 08, 2022 15:16:02 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
veso74, *str это же указатель на строку. Т.е. надо сначала еще список форматов сделать, а затем по указателю таскать нужный формат? |
|
| Автор: | Morroc [ Пт апр 08, 2022 15:22:52 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
ну вот здесь все 12 реализаций функции. Тело функции одно, изменяется лишь параметр, который изменяется, границы его изменения, да формат вывода строки с результатом. на мой взгляд у вас в принципе подход не тот. если хотите оптимизировать - делайте одну универсальную функцию для ввода данных, другую универсальную для отрисовки экрана, конечный автомат для управления тем что вводим в данный момент и т.д. |
|
| Автор: | veso74 [ Пт апр 08, 2022 15:29:19 ] |
| Заголовок сообщения: | Re: Как оптимизировать использование функций? |
char *str при передаче данных в функцию. В осн. прогр. есть как массив символов: char txt[] = "test"; и при использовании: LCD_print(txt); --- Morroc, он, вероятно, пытается это сделать, и у него, вероятно, возникают трудности с передачей string на универсальную функцию. |
|
| Страница 1 из 4 | Часовой пояс: UTC + 3 часа |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|


