Почему скорость выполнения цикла while меняется со временем?

У нас есть проблема со временем в цикле C while. в одной части программы цикл while получает информацию от датчика по протоколу SPI и сохраняет ее в базе данных Mysql. Проблема возникает, когда мы проверяем сохраненные данные. Например, в базе хранится 600 данных в секунду, но через несколько секунд количество хранимых данных уменьшается до 400, а через несколько секунд возвращается к 600 в секунду и так далее. Я знаю, что скорость передачи данных с датчика работает на фиксированных часах и не может быть изменена. Но я не знаю, где эта проблема возникает.

вот код цикла while в c:

 while(1)
        {

            tx_buff[0] = 0x08 ;
            tx_buff[0] = (tx_buff[0] << 1) | 1;
            tx_buff[1] = 0xFF;
            tx_buff[2] = 0xFF;
            tx_buff[3] = 0xFF;
            tx_buff[4] = 0xFF;
            tx_buff[5] = 0xFF;
            tx_buff[6] = 0xFF;
            tx_buff[7] = 0xFF;
            tx_buff[8] = 0xFF;
            tx_buff[9] = 0xFF;
            tinkerboard_set_gpio_state(24, LOW);
            tinkerboard_spi_transfer(SPI2, tx_buff, rx_buff,10, mode);
            tinkerboard_set_gpio_state(24, HIGH);
            X_unsigned = (rx_buff[1]<<16) | (rx_buff[2]<<8)| (rx_buff[3]);
            X_unsigned = X_unsigned >> 4;
            X_signed = adc24to32(X_unsigned);
            Y_unsigned = (rx_buff[4]<<16) | (rx_buff[5]<<8)| (rx_buff[6]);
            Y_unsigned = Y_unsigned >> 4;
            Y_signed = adc24to32(Y_unsigned);
            Z_unsigned = (rx_buff[7]<<16) | (rx_buff[8]<<8)| (rx_buff[9]);
            Z_unsigned = Z_unsigned >> 4;
            Z_signed = adc24to32(Z_unsigned);

printf(" X=%5.4f Y=%5.4f Z=%5.4f \n",
X_signed*0.0039,Y_signed*0.0039,Z_signed*0.0039);
sprintf(query, "INSERT INTO PO(x,y,z) VALUES(%5.4f,%5.4f,%5.4f)",
X_signed*0.0039,Y_signed*0.0039,Z_signed*0.0039);

//conect to sql
     mysql_query(conn, query);
    
        }
and stores it in a mysql database - это операция дискового ввода-вывода (файловой системы)?
goodvibration 14.12.2020 10:46

Если да, то это не то, на что следует полагаться для ответов RT, поскольку FS в любой момент может «выбрать» реорганизацию, что приведет к значительному отставанию. Как правило, вы должны настроить другой поток для выполнения этой операции и из своего цикла while отправить его как сообщение в этот другой поток.

goodvibration 14.12.2020 10:49

да это .@ goodvibration

Hooman.AS 14.12.2020 10:51

То же самое касается печати BTW - в идеале у вас должен быть еще один поток только для этого (также известный как поток регистрации).

goodvibration 14.12.2020 10:53

Я должен попробовать этот путь. сохраненные данные в другом потоке?

Hooman.AS 14.12.2020 11:00

Вы настраиваете несколько потоков, которые взаимодействуют друг с другом через очереди сообщений. Здесь вам нужно отправить эти данные в поток, который сохранит их в файле SQL. В тех случаях, когда операция FS занимает больше времени, очередь сообщений этого потока становится более заполненной (с сообщениями, которые еще не обработаны). Затем, как только эта операция будет завершена, очередь постепенно «вернется в нормальное состояние», и в ней будет находиться всего несколько сообщений. Поэтому вы должны убедиться, что используете достаточно большую очередь сообщений, чтобы справляться со случайными задержками.

goodvibration 14.12.2020 11:14

Некоторые планировщики Unix также штрафуют процессы, которым было предоставлено время выполнения за последние несколько секунд, в пользу тех, которым этого не требовалось. Это может привести к колебаниям процессорного времени.

Jens 14.12.2020 11:57

Наша ОС является дистрибутивом Debian. если проблема оттуда, как мы можем ее решить? Я имею в виду, есть ли способ решить эту проблему вообще? @Jens

Hooman.AS 14.12.2020 12:24

Вы можете поиграть со значением nice для процесса, увеличив приоритет планирования. См. справочную страницу.

Jens 14.12.2020 16:36
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
2
9
202
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Две вещи.

Сначала откройте соединение с сервером MySql и повторно используйте его. Не открывайте новое соединение для каждой вставки: это слишком медленно. И имейте в виду, что объекты подключения MySql не являются потокобезопасными.

Во-вторых, MySql наиболее эффективно обрабатывает массовые операции вставки, если многие из них объединяются в одну транзакцию базы данных. И ваш проект выполняет массовые вставки.

Подходящее количество операций вставки для объединения составляет 100 или около того. Это повышает эффективность сервера MySql, поскольку большая часть работы по вставке выполняется при фиксации транзакции. Если вы не завернете свои вставки в START TRANSACTION; и COMMIT;, MySql сделает автоматическую фиксацию. Это означает, что каждая вставка также является транзакцией, и накладные расходы выходят из-под контроля.

Это достаточно легко организовать. При первом открытии соединения установите для переменной обратного отсчета значение 100 и введите START TRANSACTION; в MySql.

Когда вы делаете каждую вставку, уменьшайте переменную обратного отсчета. Когда он достигнет нуля, сбросьте его и сделайте COMMIT;, а затем еще START TRANSACTION;.

Это не превратит ваш проект в проект жесткого реального времени, но очень поможет с накладными расходами MySql.

И рассмотрите возможность запуска MySql на другом хост-компьютере.

Другие вопросы по теме