Я работаю над скриптом, который анализирует и отображает информацию из файла журнала базы данных. Некоторые примеры loglines могут быть:Компактная структура данных для хранения анализируемых строк журнала в Go (т. Е. Компактная структура данных для множественных перечислений в Go)
Tue Dec 2 03:21:09.543 [rsHealthPoll] DBClientCursor::init call() failed
Tue Dec 2 03:21:09.543 [rsHealthPoll] replset info example.com:27017 heartbeat failed, retrying
Thu Nov 20 00:05:13.189 [conn1264369] insert foobar.fs.chunks ninserted:1 keyUpdates:0 locks(micros) w:110298 110ms
Thu Nov 20 00:06:19.136 [conn1263135] update foobar.fs.chunks query: { files_id: ObjectId('54661657b23a225c1e4b00ac'), n: 0 } update: { $set: { data: BinData } } nscanned:1 nupdated:1 keyUpdates:0 locks(micros) w:675 137ms
Thu Nov 20 00:06:19.136 [conn1258266] update foobar.fs.chunks query: { files_id: ObjectId('54661657ae3a22741e0132df'), n: 0 } update: { $set: { data: BinData } } nscanned:1 nupdated:1 keyUpdates:0 locks(micros) w:687 186ms
Thu Nov 20 00:12:14.859 [conn1113639] getmore local.oplog.rs query: { ts: { $gte: Timestamp 1416453003000|74 } } cursorid:7965836327322142721 ntoreturn:0 keyUpdates:0 numYields: 15 locks(micros) r:351042 nreturned:3311 reslen:56307 188ms
Не каждый лаглинь содержит все поля, но некоторые из полей мы разбором из включают в себя:
- Datetime
- Запрос Продолжительность
- Название Тема
- Номер соединения (например, 1234, 532434, 53433)
- Уровень ведения журнала (например, предупреждение, ошибка, информация, отладка и т. Д.)
- Элемент регистрации (например, Хранение, журнал, команды, Indexin и т.д.)
- Тип операции (например, запрос, вставка, удаление и т.д.)
- пространство имен
Общая файл_журнала часто может быть достаточно большой (несколько сотен MBs до купе ГБ). В настоящее время скрипт находится в Python, а также в полях, он также хранит исходную исходную логическую строку, а также токенизированную версию - результирующее потребление памяти, хотя на самом деле несколько кратных первоначальному размеру файла журнала. Следовательно, потребление памяти является одной из основных вещей, которые я хотел бы улучшить.
Для удовольствия/обучения я решил попробовать повторить это в Go и посмотреть, можем ли мы использовать более компактную структуру данных.
Многие из полей являются перечислениями (перечислениями) - для некоторых из них заранее известен набор значений (например, логгирование, элемент регистрации). Для других (например, имя потока, номер подключения, пространство имен) мы разработаем набор во время выполнения при анализе файла журнала.
Планируемые изменения
Во-первых, многие из этих перечислений, хранятся в виде строк. Поэтому я предполагаю, что одним из улучшений будет переход на использование чего-то вроде uint8
для его сохранения, а затем либо с помощью констант (для тех, которые мы знаем заранее), либо с какой-то таблицей сопоставления с исходной строкой (для которые мы разрабатываем.) Или есть ли какие-либо другие рекомендации, которые я бы предпочел для consts по сравнению с какой-либо структурой отображения?
Во-вторых, вместо сохранения исходной строки в виде строки мы можем, вероятно, сохранить смещение обратно к исходному файлу на диске.
Вопросы
- ли вы какие-либо вопросы, либо из двух запланированных изменений выше? Являются ли они хорошей отправной точкой?
- Есть ли у вас какие-либо другие советы/рекомендации по оптимизации потребления памяти, как мы храним логлайн?
- Я знаю, что для растровых изображений есть такие вещи, как реверсивные растровые изображения (http://roaringbitmap.org/), которые представляют собой сжатые растровые изображения, которые вы все равно можете получить/изменить нормально, пока они сжаты. По-видимому, общий термин для подобных вещей - сжатые структуры данных. Однако существуют ли какие-либо эквиваленты ревущих растровых изображений, но для перечислений?Или любой другой умный способ хранения этого компактного?
- Я также подумал о фильтрах цветения и, возможно, использовал их для хранения того, был ли каждый логлайн установлен в наборе (т.е. предупреждение уровня ведения журнала, ошибка уровня регистрации) - однако он может быть только в одном из этих наборов, Знайте, если это имеет смысл. Кроме того, не уверен, как обрабатывать ложные срабатывания.
Мысли?
Непонятно, что вы просите. Просьба уточнить вашу конкретную проблему или добавить дополнительные сведения, чтобы точно указать, что вам нужно.Как это написано в настоящее время, трудно точно сказать, что вы просите. Например, укажите образец строк журнала. – peterSO
@peterSO Конечно, я добавил заголовки и попытался уточнить вопрос немного больше - дайте мне знать, если это будет полезно. – victorhooi
Что касается перечислений, вы можете определить тип ('type LogLevel int'), а затем использовать' iota' в своих определениях const ('const (INFO LogLevel = iota' then,' DEBUG', 'ERROR' и т. Д.) См. http://play.golang.org/p/PjrjSVIvrS https://golang.org/ref/spec#Iota – Intermernet