Как ускорить время возврата файла ReadFile?
Я разрабатываю приложение, которое считывает фиксированный пакет данных из com-порта с регулярными интервалами в 50 мс. Я использую
CreateFile
и ReadFile
чтобы открыть и прочитать из порта соответственно. Существует небольшое количество обработки, которая происходит с данными, которые считываются.Поскольку выбор времени жизненно важен в таком приложении, я решил проверить, сколько времени занимает каждая из отдельных задач. То
ReadFile
функция вызывалась каждые 50 мс или всякий раз, когда EV_RXCHAR
событие произошло. Обработка занимает едва ли миллисекунду. Это все хорошо. Но ... ReadFile
функция занимает в среднем 15 мс, чтобы вернуться. Кажется, что это ужасно много времени для чтения данных из порта. Я отправляю данные в порт через стороннее приложение, которое записывает данные в виде пакетов, так что это не может быть (я думаю) из-за его скорости записи.Это становится проблемой из-за следующего: я сделал вышеуказанные тесты с виртуальными com-портами. Когда я тестирую его с помощью некоторого физического оборудования, затраченное время может варьироваться от 47 мс до 127 МС. Аппаратное обеспечение - это карта, предназначенная для упаковки данных и отправки их в виде пакетов. Такая задержка приводит к тому, что мое приложение довольно быстро выходит из синхронизации.
Поэтому любые предложения о том, как я могу ускорить это или, возможно, попробовать другую стратегию, будут высоко оценены.
PS: я делаю неперекрывающееся чтение и запись специально.
Что я уже пробовал:
Я не знаю, что здесь добавить, поэтому добавляю свой код функции чтения. Он находится в бесконечном цикле, пока не проинструктирован иначе.
void CGCUGUIDlg::fnRead() { while(m_bCount==true) { { WaitCommEvent(m_hComm,&dwEventMask,NULL); if(dwEventMask==EV_RXCHAR) { DWORD NoBytesRead; BYTE abBuffer[100]; if(ReadFile((m_hComm),&abBuffer,sizeof(abBuffer),&NoBytesRead,0)) //This takes over 47ms with physical hardware { midTime1 = GetTickCount(); if(NoBytesRead==45) { if(abBuffer[0]==0x10&&abBuffer[1]==0x10||abBuffer[0]==0x80&&abBuffer[1]==0x80) { this->fnSetData(abBuffer); } else { CString value; value.Append("Header match failed"); this->SetDlgItemText(IDC_RXRAW,value); } } else if (NoBytesRead<45 && NoBytesRead>0) { CString value; value.Append(LPCTSTR(abBuffer),NoBytesRead); value.Append("\r\nInvalid Packet Size"); this->SetDlgItemText(IDC_RXRAW,value); } } else { DWORD dwError2 = GetLastError(); CString error2; error2.Format(_T("%d"),dwError2); this->SetDlgItemText(IDC_RXRAW,error2); } } } } CloseHandle(m_hComm); }
PS: Я приношу свои извинения за ужасное форматирование и случайные скобки.
PIEBALDconsult
Это не очень поможет, но я думаю, что вы должны создать экземпляр массива-BYTE abBuffer[100] - один раз, перед входом в цикл, а не создавать его на каждом цикле цикла.
Кроме того, то, что я делал в прошлом, заключается в том, чтобы чтение и обработка выполнялись в отдельных потоках.
То есть разделите заботы.
Я всегда слышу мантру моего школьного футбольного тренера: "получи это, избавься от этого; получи это, избавься от этого..."
TheLostJedi
Thank you for that reply!! The reason I create a new instance of the buffer each time is to ensure I have an empty buffer every time, and also it's kind of neat that the previous buffer gets cleaned up automatically once the scope ends. Also, this read is happening in a separate worker thread and because processing can happen only after the read is done I didn't think too much about allocating separate resources for the processing. But the main issue is that I can time and see that the ReadFile is taking a massive amount of time. Just that one line. The total time of each loop is actually the ReadFile time plus 1 or 2ms. I realise that these are inbuilt API calls, but I was hoping there was a way to speed it up.
Kornfeld Eliyahu Peter
Если синхронизация важна, вы не можете установить фиксированный временной интервал, а только использовать события для связи...
Com - порты построены на блоке UART, который может работать с различной скоростью (baudrate), чтобы соответствовать подключенному устройству...
Вы не показали, как вы открыли порт, но вы можете попробовать другую настройку скорости передачи данных...
TheLostJedi
Спасибо Вам за ответ!! Я использую чтение на основе событий именно по той причине, о которой Вы упомянули; синхронизация почти невозможна при синхронизированном чтении не в последнюю очередь из-за неточных таймеров.
Я прошу прощения за то, что не показал, как был открыт порт. Он был установлен на скорость передачи данных 115200 бит / с, и, к сожалению, это не может быть изменено и является тем же самым для устройства, отправляющего данные. Но я предполагаю, что это поставило бы конечный нижний предел времени, которое занимает каждое чтение, верно?
Kornfeld Eliyahu Peter
Вы написали: "считывает фиксированный пакет данных из com-порта с регулярными интервалами в 50 мс"... Это не похоже даже на базис :-)
115200 - это вообще хорошая скорость. Передача 100 байт на этой скорости должна занять около 10 мс, так что это звучит хорошо...
Две вещи:
1. Почему вы закрываете com-порт в конце функции?
2. Есть ли у вас инструмент мониторинга портов, чтобы увидеть, что на самом деле идет и приходит?
TheLostJedi
Данные передаются с такой скоростью, я не могу это контролировать. Я читаю в событийной манере, проверяя наличие события EV_RXCHAR.
1. Это был мой способ прекратить чтение и выйти из потока. Флаг (m_bCount) будет превращен в false из моего основного потока, чтобы сигнализировать этому потоку чтения, чтобы остановить все.
2. Я проверил, что. Все передаваемые данные хороши.
Моя проблема все еще заключается в том, что после всего этого функция ReadFile занимает много времени, чтобы вернуться, что на самом деле не имеет для меня никакого смысла.