Как стать автором
Обновить

Комментарии 22

А что сохраняется — тупо текущее состояние? История правок (с возможностью undo) не сохраняется? Что происходит при крэше приложения/ОСи?

Я как бы намекаю на одно типовое решение…
Сохраняется текущее состояние без возможности undo.
Намек, что-то не очень понял. Вы про VCS?

При крэше/блэкауте сохранится весь текст, за исключением, возможно сделанных в последние 2-3 секунды.

Странное сравнение:


  1. Если уж сравнивать sqlite и nosql, то логично (по-моему) в случае с sqlite
    использовать sqlite json extension,
    или в C# обертку для sqlite json еще "не завезли"?


  2. По поводу времени "write" для sqlite, хотелось бы увидеть какой journal mode sqlite
    использовался, какой его аналог в LiteDB, сколько транзакций во время записи было
    в случае sqlite и LiteDB
Не очень пойму как мог бы помочь sqlite json extension. Это ведь набор функций для работы с json или я не прав?
Если это действительно всего лишь набор функций, то думаю еще бы потерял в скорости, генерируя для вставки в базу из текста json, а потом разбирая его, пусть даже последним бы и занималась SQLite. SQLite реляционная база и я ожидал от нее наибольшей производительности именно если складывать в нее реляционные данные.

Режим журналирования SQLite: PRAGMA journal_mode = OFF
Использовал по транзакции на файл.
Так же и litedb все льется одним insert'ом, что, пусть и с натяжкой, с натяжкой можно считать одной транзакцией.

Сферические цифры по сохранению несложных POCO объектов (диск hdd):


    [Serializable]
    public class MscEvent
    {
        public Int64 msisdn;
        public DateTime chargingdatetime;
        public Int64 chargeableduration;
        public Int64 bnumber;
        public Int16 typeofrecord;
        public Int16 sourceId;
    }

Testing on 1 000 000 events
[Sqlite Journal Mode=Off] write/read  89462/287835 op/s] time elapsed write/read 11,1778348 / 3,4742009 s]
[LevelDbBatch MsgPackSerializer NoCompression] write/read  178024/501050 op/s] time elapsed write/read 5,6172074 / 1,995808 s]
[LiteDb] write/read  82346/218760 op/s] time elapsed write/read 12,1438787 / 4,5712058 s]
[CsvBench] write/read  749532/392383 op/s] time elapsed write/read 1,3341648 / 2,5485245 s]
[SerializedFile MsgPackSerializer] write/read  2193977/675174 op/s] time elapsed write/read 0,4557931 / 1,4810979 s]
[SerializedFile JsonSerializer] write/read  301375/317855 op/s] time elapsed write/read 3,3181228 / 3,1460794 s]
[SerializedFile WireSerializer] write/read  2214939/2129023 op/s] time elapsed write/read 0,4514795 / 0,4696988 s]

Testing on 10 000 000 events
[Sqlite Journal Mode=Off] write/read  89674/285626 op/s] time elapsed write/read 111,514258 / 35,0107894 s]
[LevelDbBatch MsgPackSerializer NoCompression] write/read  136594/488647 op/s] time elapsed write/read 73,2091265 / 20,4646613 s]
[LiteDb] write/read  75120/196484 op/s] time elapsed write/read 133,1192939 / 50,8947216 s]
[CsvBench] write/read  709238/398380 op/s] time elapsed write/read 14,099631 / 25,10166 s]
[SerializedFile MsgPackSerializer] write/read  1533240/673520 op/s] time elapsed write/read 6,5221352 / 14,8473537 s]
[SerializedFile JsonSerializer] Необработанное исключение: OutOfMemoryException.
[SerializedFile WireSerializer] write/read  1567601/2205764 op/s] time elapsed write/read 6,3791707 / 4,5335747 s]

C leveldb пробовал разные параметры компрессии, буферов и т.д. (например new Options() {Compression = CompressionType.SnappyCompression, WriteBufferSize = 128*1024*1024})


Вообщем вот. Выводы делайте сами

Мой тест имел кое-какую специфику, о которой я писал:
Мы храним текст построчно, а значит хотим и сохранять и вычитывать тоже построчно. К тому же при вычитке одним куском рискуем нарваться на огромный memory allocation, и нарваться на него же при сохранении, если для этого нужно склеить все строки вместе. В LiteDB есть возможность скормить IEnumerable и он отлично сохранится, и отлично вычитается. В SQLite строка в документе представляла собой строку в базе. Получается для документа в 100 строк, выполнялось 100 инсертов, что было дольше чем выполнить 1 в LiteDB.
А в сторону ESENT не смотрели? По скорости быстрее, чем SQLite.
Как-то в Сети не почти ничего про эту технологию. Можете рассказать или навести на правильные ссылки?
https://en.wikipedia.org/wiki/Extensible_Storage_Engine

https://blogs.msdn.microsoft.com/windowssdk/2008/10/22/esent-extensible-storage-engine-api-in-the-windows-sdk/

для c#
https://www.nuget.org/packages/ManagedEsent/
Спасибо. Гляну в эту сторону.
Это низкоуровневый ISAM движок, который раньше
ESENT очень широко используется внутри самой Windows, это нативное win32 API со всеми последствиями, но есть обёртка под .NET и работает это решение даже на WindowsPhone и в UWP приложениях (Даже в плеере Zune в качестве БД использовался ESENT). Потребляет больше памяти чем SQLite, но и больше функционал (снапшот изоляция транзакций, полное журналирование, и т.д.). Из минусов пишут такое: «своеобразные требования к thread-ингу. Приложение может открыть сколько угодно параллельных сессий. Но одна сессия должна жить в рамках одного треда.»
И до 7ки он вроде как был жестко прибит гвоздями к NTFS и зависел от размера кластера, но потом отвязали от NTFS.

https://www.codeproject.com/articles/52715/extensible-storage-engine
https://msdn.microsoft.com/en-us/library/gg269259(v=exchg.10).aspx
https://managedesent.codeplex.com/
https://en.wikipedia.org/wiki/Extensible_Storage_Engine
Спасибо за наводку на LiteDB, пригодится.
тогда добавлю наводку на db4o
В винде же есть shadow copy — реализующий CoW механизмы. Да, вроде как ограничение — снимки распространяются на целый раздел, но выделить отдельный раздел под хранение рабочих файлов, получив взамен все плюшки мгновенных снапшотов состояния и эффективного их хранения, по-моему, должны всё покрывать. И самое главное — это уже есть в самой ОС.
Почитал про эту функцию. Насколько я понимаю, для того чтобы ею воспользоваться файл должен сперва оказаться на диске, верно? Если это так, то нам это не подходит, по причине, что интерес этой фичи представляется именно для несохраненных/измененных файлов. Или я где-то не прав?
Да, конечно, файл должен быть на диске.
Но вы хотите сказать, что у вас даже временных файлов нет? Т.е всё всегда в памяти? Задача у вас описана очень туманно. Но обычно IDE всё таки хранят «несохраненные» файлы, чтобы иметь возможность восстановить хотя бы часть работы при падении приложения/ОС.
Так это как раз и есть та функция, которая позволит сохранить работу пользователя.
Кто-то это реализует через временные файлы, мы решили делать это через встраиваемую базу.
Еще как вариант LMDB. По максимуму использует оперативку, очень хороши флашит данные на диск. В базе размером 25гб и с количеством записей 300млн поиск выполняется за 1-3мс при условии что SSD на вирт машине.
Единственный минус — должен быть один писатель. Но кроссплатформенный
Спасибо за наводку.
Если по максимуму использует оперативную память, то это может для нас быть проблемой.
В 2017 году MS VS и MS SMS это 32 битные приложение, а значит мы делим с ними жалкие 3.25(по факту меньше) оперативной памяти.
brightstardb не пробовали? было бы интересно сравнение
Не случилось, но спасибо за наводку. Глану в этом направлении
если доберетесь раньше — было бы интересно узнать мнение о бенчмарках и размерах кода в сравнении с LiteDB…
функциональность у b* предлагает больше возможностей на первый взгляд
еще в разное время попадали в поле зрения:
https://ndatabase.codeplex.com/
https://github.com/Wintellect/SterlingDB
оба проекта в затишье похоже
но последний зацепился из за того что был дополнен драйвером к azure tables, а это дешевое хранилище… если актуально конечно
а ndatabase показался довольно проработанным в плане примеров, даже linqpad поддержан. но мне показалось что он не претендент по скоростным возможностям ;((
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории