jenya7 0 19 октября, 2015 Опубликовано 19 октября, 2015 (изменено) · Жалоба я логирую данные во внешнюю память. размерность памяти 8 бит. каждая запись 16 бит то есть каждая запись берет 2 байта. текущий адрес записи я храню в глобальной переменной - param1.logNum. и тут я задумался над оптимальным алгоритмом - считать последних n записей. причем мне эти записи надо послать пакетами по 18 байт каждый пакет. Кое что я набросал. void BLUENRG_SendLog(void) //send n deltas from the last { uint32_t chank = 18; //DELTA_SIZE * AVAILABLE_BUF_SIZE; uint32_t last_log_addr = param1.logNum * DELTA_SIZE; uint32_t packet_size; uint32_t tx_num=0; uint32_t current_addr = last_log_addr - (chank * tx_num); //check if the overflow occurred while (current_addr > START_LOG_ADRESS) { packet_size = chank; uint8_t buf[packet_size]; LOGGER_Readlog(current_addr, packet_size, buf); SendBuf(buf); tx_num++; current_addr = last_log_addr - (chank * tx_num); } // send the rest of data ??? } Но мне это не нравиться. Может лучше отсчитать и начать с младшего адреса? Проще и не надо проверять ушел ли я за границы начального адреса. Изменено 19 октября, 2015 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CrimsonPig 0 19 октября, 2015 Опубликовано 19 октября, 2015 · Жалоба я логирую данные во внешнюю память. размерность памяти 8 бит. каждая запись 16 бит то есть каждая запись берет 2 байта. текущий адрес записи я храню в глобальной переменной - param1.logNum. и тут я задумался над оптимальным алгоритмом - считать последних n записей. причем мне эти записи надо послать пакетами по 18 байт каждый пакет. Но мне это не нравиться. Может лучше отсчитать и начать с младшего адреса? Проще и не надо проверять ушел ли я за границы начального адреса. Не проще ли хранить ваши записи лога в кольцевом буфере (ring buffer), и выбирать из него данные по мере необходимости ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 19 октября, 2015 Опубликовано 19 октября, 2015 · Жалоба Не проще ли хранить ваши записи лога в кольцевом буфере (ring buffer), и выбирать из него данные по мере необходимости ? в принципе это и есть большой кольцевой буфер. но данные все равно надо выбрать. скажем я хочу посмотреть последние 100 записей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CrimsonPig 0 19 октября, 2015 Опубликовано 19 октября, 2015 · Жалоба в принципе это и есть большой кольцевой буфер. но данные все равно надо выбрать. скажем я хочу посмотреть последние 100 записей. Ну так прочитайте их с головы кольцевого буфера, а не с хвоста :) Делаем копию указателя (или индекса, зависит от имплементации) записи, уменьшаем его на нужное кол-во записей (по модулю размера буфера + отслеживание пересечения границы чтения) и читаем с инкрементом. Атомарность, проверки на переполнение\опустошение и прочие невнятные мелочи опускаем для простоты :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 16 19 октября, 2015 Опубликовано 19 октября, 2015 · Жалоба Но мне это не нравиться. Может лучше отсчитать и начать с младшего адреса? Проще и не надо проверять ушел ли я за границы начального адреса. (выделено мной) Перфекционизм - это опасно и вредно. Работает? успевает? не мешает другим жить? тогда не трогайте! Просто идите дальше. А по существу: есть некоторые общие правила, например- упрощать расчеты, выполняемые в цикле. Например, зачем у Вас там current_addr каждый раз пересобирается с нуля? вполне достаточно просто уменьшать ее на chank. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 5 19 октября, 2015 Опубликовано 19 октября, 2015 · Жалоба Делаем копию указателя (или индекса, зависит от имплементации) записи, уменьшаем его на нужное кол-во записей (по модулю размера буфера + отслеживание пересечения границы чтения) и читаем с инкрементом. Атомарность, проверки на переполнение\опустошение и прочие невнятные мелочи опускаем для простоты :) Если почитать-таки код в первом сообщении, там именно это и делается. "Для простоты" там, правда, нет указания, сколько же данных у нас запросили. И ещё, там нет кольцевого буфера (запись не вижу, а на чтение - точно нету!). Зато есть как минимум пара лишних переменных (чтоб никто не догадался). И очень удобный формат, в котором они возвращаются - полностью всё перепутано. Я б ТЗ стряс для начала. Сколько записей, сколько хранить, сколько считывать (считывать только так, или это только один из интерфейсов), ... А то опять угадайка "что хотел сказать автор" с нерабочим кодом... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CrimsonPig 0 19 октября, 2015 Опубликовано 19 октября, 2015 · Жалоба Я б ТЗ стряс для начала. Сколько записей, сколько хранить, сколько считывать (считывать только так, или это только один из интерфейсов), ... А то опять угадайка "что хотел сказать автор" с нерабочим кодом... Мне зачастую проще намекнуть, как надо было бы сделать по-хорошему (естественно, с моей точки зрения), чем разбираться в обрывках чужого кода и строить догадки по поводу того, что хотел автор.. Пусть делает, как хочет :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 19 октября, 2015 Опубликовано 19 октября, 2015 (изменено) · Жалоба Если почитать-таки код в первом сообщении, там именно это и делается. "Для простоты" там, правда, нет указания, сколько же данных у нас запросили. И ещё, там нет кольцевого буфера (запись не вижу, а на чтение - точно нету!). Зато есть как минимум пара лишних переменных (чтоб никто не догадался). И очень удобный формат, в котором они возвращаются - полностью всё перепутано. Я б ТЗ стряс для начала. Сколько записей, сколько хранить, сколько считывать (считывать только так, или это только один из интерфейсов), ... А то опять угадайка "что хотел сказать автор" с нерабочим кодом... по моему все понятно - надо считать N-ное количество записей. считывается всегда с последней. и какая разница кольцевой буфер или нет? Изменено 19 октября, 2015 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 5 19 октября, 2015 Опубликовано 19 октября, 2015 · Жалоба Хорошая практика - рисовать ПО на бумажке, в виде квадратиков и стрелочек. Ещё очень полезная абстракция - рисовать буфер в виде последовательности квадратиков-ячеек, с различными положениями указателей на этот буфер. Для выяснения вопроса "какая разница, кольцевой буфер" предлагаю нарисовать его в положении "добавление пошло на второй круг, положение указателя на добавление равно трём, запросили десять записей". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
CrimsonPig 0 19 октября, 2015 Опубликовано 19 октября, 2015 · Жалоба Хорошая практика - рисовать ПО на бумажке, в виде квадратиков и стрелочек. Ещё очень полезная абстракция - рисовать буфер в виде последовательности квадратиков-ячеек, с различными положениями указателей на этот буфер. Угу. еще полезно рассматривать кольцевой буфер как конечный автомат с состояниями Empty, HasData, Overflow. Помогает решить сразу несколько проблем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 19 октября, 2015 Опубликовано 19 октября, 2015 · Жалоба вы знаете на второй круг он пойдет через год. я к тому времени побеспокоюсь об этом. сейчас я решаю совсем другую задачу - взять энное количество последних записей. саму задачу НЕ должно волновать откуда я беру записи. единственно что надо предусмотреть - не выйти за границы записи. задача проста и ясна и я не понимаю зачем разводить срач на ровном месте. "добавление пошло на второй круг…” вы не волнуйтесь - на втором круге все будет хорошо Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 19 октября, 2015 Опубликовано 19 октября, 2015 (изменено) · Жалоба uint32_t chunk = CHUNK_SIZE; uint32_t last_log_addr = (logNum * DELTA_SIZE) + START_LOG_ADRESS; uint32_t packet_size; int32_t current_addr = last_log_addr-chunk; while (current_addr > START_LOG_ADRESS) { if(current_addr - START_LOG_ADRESS >= chunk) packet_size = chunk; else packet_size = current_addr - START_LOG_ADRESS; uint8_t buf[packet_size]; LOGGER_Read(current_addr,packet_size,buf); SendBuf(buf); current_addr -= chunk; } если не лень функцию можно сделать абсолютно генерик стайл без привязки к какой либо железке кольцевая она там или нет. Изменено 19 октября, 2015 пользователем Jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alexashka 0 20 октября, 2015 Опубликовано 20 октября, 2015 · Жалоба ... int32_t current_addr = last_log_addr-chunk; ... if(current_addr - START_LOG_ADRESS >= chunk) packet_size = chunk; else packet_size = current_addr - START_LOG_ADRESS; ... current_addr -= chunk; } если не лень функцию можно сделать абсолютно генерик стайл без привязки к какой либо железке кольцевая она там или нет. Закольцовка имеет смысл если записи идут и идут, а считывание всё откладывается. Тогда закольцевав буфер сохраняем последние записи (ессно затерев самые старые из них). В конце наверное нужно вычитать не chunk, а packet_size (на случай если блок был укороченный). И похоже нужно смотреть разницу не между текущим адресом и стартовым, а между конечным и стартовым (для примера можно посмотреть что будет если в буфере было 5 записей а считывается 18 -при первом же заходе в функцию будем сразу из нее вылетать, т.к current_addr < START_LOG_ADRESS). Не понятно зачем нужна переменная chunk, если она используется только как копия константы CHUNK Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 26 октября, 2015 Опубликовано 26 октября, 2015 · Жалоба Закольцовка имеет смысл если записи идут и идут, а считывание всё откладывается. Тогда закольцевав буфер сохраняем последние записи (ессно затерев самые старые из них). В конце наверное нужно вычитать не chunk, а packet_size (на случай если блок был укороченный). И похоже нужно смотреть разницу не между текущим адресом и стартовым, а между конечным и стартовым (для примера можно посмотреть что будет если в буфере было 5 записей а считывается 18 -при первом же заходе в функцию будем сразу из нее вылетать, т.к current_addr < START_LOG_ADRESS). Не понятно зачем нужна переменная chunk, если она используется только как копия константы CHUNK спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться