WAL немного побеждает. но 6 минут нигде нет
- HackFresse давай искать причину почему у тебя так?
Для повторения эксперимента запускать тестовую бетку с такими ключами
FlylinkDC.exe /sqlite_use_memory - используется журнал транзакций в памяти
FlylinkDC.exe /sqlite_use_wal - режим WAL
FlylinkDC.exe - (без ключа) режим = PERSIST
CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));
INSERT INTO t1 VALUES(1,13153,'thirteen thousand one hundred fifty three');
INSERT INTO t1 VALUES(2,75560,'seventy five thousand five hundred sixty');
... 995 lines omitted
INSERT INTO t1 VALUES(998,66289,'sixty six thousand two hundred eighty nine');
INSERT INTO t1 VALUES(999,24322,'twenty four thousand three hundred twenty two');
INSERT INTO t1 VALUES(1000,94142,'ninety four thousand one hundred forty two');
PostgreSQL: 4.373
MySQL: 0.114 SQLite 2.7.6: 13.061
SQLite 2.7.6 (nosync): 0.223
Because it does not have a central server to coordinate access, SQLite must close and reopen the database file, and thus invalidate its cache, for each transaction. In this test, each SQL statement is a separate transaction so the database file must be opened and closed and the cache must be flushed 1000 times. In spite of this, the asynchronous version of SQLite is still nearly as fast as MySQL. Notice how much slower the synchronous version is, however. SQLite calls fsync() after each synchronous transaction to make sure that all data is safely on the disk surface before continuing. For most of the 13 seconds in the synchronous test, SQLite was sitting idle waiting on disk I/O to complete.
Потому что он не имеет центрального сервера для координации доступа, SQLite должен закрыть и снова открыть файл базы данных, и, таким образом недействительным свой кэш, для каждой транзакции. В этом тесте, каждый оператор SQL отдельная сделка так что файл базы данных должен быть открыт и закрыт и кэш должен быть промыт 1000 раз. Несмотря на это, асинхронная версия SQLite еще почти так же быстро, как MySQL. Обратите внимание, насколько медленнее синхронной версии, однако. SQLite называет Fsync () после каждого синхронного сделки, чтобы убедиться, что все данные благополучно на поверхности диска, прежде чем продолжить. Для большинства из 13 секунд в синхронном теста, SQLite сидел простаивает, ожидая на диске ввода / вывода, чтобы закончить.
Что значит "открыть файл, записать изменения, закрыть файл" (одна транзакция)? из официального FAQ, почему insert тормозят
A transaction normally requires two complete rotations of the disk platter, which on a 7200RPM disk drive limits you to about 60 transactions per second.
Два полных оборота диска + позиционирование головки, только чтобы записать одну мелкую порцию информации, повторять долго и упорно. Это если кроме флайлинка никаким процессам в системе жесткий не нужен, иначе будут тормоза и хруст
Что значит "открыть файл, записать изменения, закрыть файл очень много раз" для владельцев супер быстрых SSD? Именно, ускоренную выработку и смерть SSD-диска.
Чуть перефразируя - "флайлинк убивает любой винт, просто на моем это больше заметно". А по поводу
Массовые инсерты я не знаю как сделать - у меня функция не тупо инсертит, она перед этим еще и ищет чтобы там не было
такого значения + естественно возвращается ID записи которую нашла или только что вставила.
Как поменять алгоритм пока не знаю.
Всё довольно элементарно - брать информацию пачкой, вместо 1 строки обрабатывать массив , записывать информацию пачкой. Таблицы держать в памяти, периодически скидывая на диск только "полезную" инфу
HackFresse писал(а):Всё довольно элементарно - брать информацию пачкой, вместо 1 строки обрабатывать массив , записывать информацию пачкой. Таблицы держать в памяти, периодически скидывая на диск только "полезную" инфу
у меня id-шки генерируются движком sqlite после вставки новой записи (там autoincrement)
после вставки каждой записи мне нужно это ID получить назад.
как? все эти статьи в инете про определенную задачу - массовая заливка готовых данных
у меня перед этим идет преобразование информации...
Давай я сделаю кей отключающий PRAGMA synchronous=FULL - с ней замеришь?
Но самое странное, что твои тормоза аномальные - у меня на нетбуке (atom 1,5) выполняется вся операция за 2 секунды.
кто-то в еще имеет слабый комп? проведите простой эксперимент?
Делается это так
1. включаете системный лог в настройках
2. закрываете флай
3. открываете блокнотом файл CustomLocations.ini - делаете там незначительно изменение
(например добавляете пустую строку чтобы поменялась метка времени.)
4. запускаете флай снова
5. открываете системный лог флайлинка и находите там строки [Stop ] [CustomLocations.ini]
этот кусок кидаете сюда + конфигурацию вашей системы.
такой тест ничего не даст по очень простой причине - такого числа поштучных insert не будет, только быстрое чтение (а оно быстрое). проблема в записи. надо удалять/чистить базу
HackFresse писал(а):Потому что он не имеет центрального сервера для координации доступа, SQLite должен закрыть и снова открыть файл базы данных,
Это где такой бред написан?
sqlite всегда держит файлы бд открытыми
отрыл-закрыл это в DC++ клиентах так работает лог-менеджер и сохранялка xml-конфигов
CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));
INSERT INTO t1 VALUES(1,13153,'thirteen thousand one hundred fifty three');
INSERT INTO t1 VALUES(2,75560,'seventy five thousand five hundred sixty');
... 995 lines omitted
INSERT INTO t1 VALUES(998,66289,'sixty six thousand two hundred eighty nine');
INSERT INTO t1 VALUES(999,24322,'twenty four thousand three hundred twenty two');
INSERT INTO t1 VALUES(1000,94142,'ninety four thousand one hundred forty two');
PostgreSQL: 4.373
MySQL: 0.114
SQLite 2.7.6: 13.061
SQLite 2.7.6 (nosync): 0.223
Because it does not have a central server to coordinate access, SQLite must close and reopen the database file, and thus invalidate its cache, for each transaction. In this test, each SQL statement is a separate transaction so the database file must be opened and closed and the cache must be flushed 1000 times. In spite of this, the asynchronous version of SQLite is still nearly as fast as MySQL. Notice how much slower the synchronous version is, however. SQLite calls fsync() after each synchronous transaction to make sure that all data is safely on the disk surface before continuing. For most of the 13 seconds in the synchronous test, SQLite was sitting idle waiting on disk I/O to complete.
В ней отрыто логирование всех локов и забивает лог Settings\Logs\ddos.log
использовать аккуратно только для теста.
Полный лог с моего компа http://yadi.sk/d/hIH2LezfHnhZK
Алгоритм на примере одного ключа
1. Если на вход приходит запрос активного поиска вида F?T?0?9?TTH. (с ключем "76.15.63.196:31620 F?T?0?9?TTH:VIHIJ7YAF6JIF2EQQZZC7VZYIE66JFY2P4KL6LA")
второй раз за интервал более N-сек (в конфиге прописал 10 сек) то флай его не скидывает в менеджер поиска вообще а просто поднимает счетчик появлений.
2. В потоке таймера каждые 10 +2 сек и удаляем все ключи которые лежат в таблице временной блокировки более 10 сек
Ожидаю таким алгоритмом убрать лавину запросов идущих с разных хабов а также ответную кучу UDP пакетов одному и тому-же клиенту.
что скажете?
[2014-02-12 22:15:49] FlylinkDC++ r503-beta28 build 16548 startup on machine with:
Number of processors: 2.
Processor type: x86.
Memory config:
There is 30 percent of memory in use.
There are 7.69 GiB total of physical memory.
There are 5.34 GiB free of physical memory.
Running in Windows WOW64
For maximal performance needs to update your FlylinkDC to x64 version!
OS: Microsoft Windows 8.1 Professional, 64-bit).
[2014-02-12 22:15:49] [Start] [fly-server]
[2014-02-12 22:15:49] [Step ] [fly-server] Download:http://www.fly-server.ru/etc/flylinkdc-config-r5xx.xml [0 ms]
[2014-02-12 22:15:49] [Step ] [fly-server] Download and parse - Ok! [191 ms]
[2014-02-12 22:15:49] [Stop ] [fly-server] [1 ms, Total: 192 ms]
[2014-02-12 22:15:50] safeAlter: duplicate column name: hit
[2014-02-12 22:15:50] safeAlter: duplicate column name: stamp_share
[2014-02-12 22:15:50] safeAlter: duplicate column name: bitrate
[2014-02-12 22:15:50] safeAlter: duplicate column name: ftype
[2014-02-12 22:15:50] safeAlter: duplicate column name: Sections
[2014-02-12 22:15:50] safeAlter: duplicate column name: block_size
[2014-02-12 22:15:50] safeAlter: duplicate column name: media_x
[2014-02-12 22:15:50] safeAlter: duplicate column name: media_y
[2014-02-12 22:15:50] safeAlter: duplicate column name: media_video
[2014-02-12 22:15:50] safeAlter: duplicate column name: media_audio
[2014-02-12 22:15:50] [Start] [StartUp]
[2014-02-12 22:15:50] [Step ] [StartUp] Begin load Geo IP [2 ms]
[2014-02-12 22:15:50] [Start] [GeoIp]
[2014-02-12 22:15:50] Error open D:\_dc\fl_sync_off\Settings\GeoIpCountryWhois.csv
[2014-02-12 22:15:50] [Stop ] [GeoIp] [2 ms, Total: 2 ms]
[2014-02-12 22:15:50] [Step ] [StartUp] End load Geo IP [2 ms and 4 ms after start]
[2014-02-12 22:15:50] [Step ] [StartUp] Begin load Custom Locations [2 ms]
[2014-02-12 22:15:50] [Start] [CustomLocations.ini]
[2014-02-12 22:15:56] [Start] [CustomLocation-sqlite]
[2014-02-12 22:15:58] [Stop ] [CustomLocation-sqlite] [1925 ms, Total: 1925 ms]
[2014-02-12 22:15:58] [Stop ] [CustomLocations.ini] [7816 ms, Total: 7816 ms]
[2014-02-12 22:15:58] [Step ] [StartUp] End load Custom Locations [7817 ms and 7823 ms after start]
[2014-02-12 22:15:58] [Step ] [StartUp] Begin load SSL [2 ms]
8 секунд, уже что-то. вот только
With synchronization off, SQLite is sometimes much faster, but there is a risk that an operating system crash or an unexpected power failure could damage the database.
снова вся надежда на то, что эта строчка устарела, и база не навернётся по случаю?
чтобы исключить уникальность моего компа, взял ноутбук, залил туда 28 бету, с которой всё началось, удалил всё, кроме самого *.exe и Settings\CustomLocations.ini, запустил
Спойлер
А где был взят ноутбук - он тоже старый?
как мне повторить эти 5 минут?
может ты что-то в винде накрутил на предмет записи на диск?
Синхронизацию в off убирать опасно - любой синий экран или потеря питания и база может быть разрушена.
но получается эти 5 минут из-за нее...
не могу понять почему на моих компах/нетбуках все быстро без ключей...
бгг, нечем заняться, как что-то в винде подкручивать что-то для записи на диск исключительно для каких-то тестов. я указал на проблему, что с этим дальше делать - дело ваше, от меня не зависит
Да, ноут тоже старый http://catalog.onliner.by/acer/lxrm30c018 - пень b950 на 2.1 Ghz, 4 гига оперативы, винт HDD 500 Gb SATA-II 300 Seagate Momentus 5400.6 < ST9500325AS> 2.5" 5400rpm 8Mb
Ок. добавлю данный параметр в статистику.
на выходных попробую изменить алгоритм стартовой заливки справочников.
не выкидывай свои компы на мусорку нужно на них потестить и сравнить результаты.
По теме что скажешь?
детектор ddos - все устраивает - проблема решена или что-то забыл?
Я вчера переписал алгоритм конвертации GeoIPCountryWhois.csv и CustomLocations.ini
теперь таблица fly_dic не будет вообще использоваться и название стран и провайдеров хранятся в виде текста с дублированием.
FlylinkDC_locations.sqlite потолстел от этого всего на 1М был 5024M, стал 6048M
у меня время загрузки немного сократилось.
не пропадай и появляйся вечером - нужны твои чудо-ноутбуки чтобы оценить дельту времени.
никаких чудо-компов нету, только что проверил на FlylinkDC-r503-x86-beta28-build-16573-2014.02.13-07.14.43.7z на рабочем компе
i3-2100, 4 гига оперативы, винт TOSHIBA DT01ACA050 500GB 7200 RPM 32MB Cache SATA 6.0Gb/s 3.5" (этот поставлен относительно недавно и совсем не хрустит, как мой террабайтный хитачи). Печаль http://yadi.sk/d/kD6b9EDcHoqH6
Алгоритм воспроизведения -
1) скачать http://www.fly-server.ru/install/r5xx/s ... 7.14.43.7z (более свежего не заметил)
2) распаковать в произвольную папку
3) ключевое условие - удалить всё, кроме файла FlylinkDC.exe и папки Settings . Должен быть только файл программы и CustomLocations.ini для обработки, никаких предзаполненных баз, это очень важно, потому что проблема в записи
4) запустить FlylinkDC.exe
Могу научить делать такие действия через тимвьювер на любом компе/ноуте/нетбуке без ssd (там всё на порядок быстрее), тогда не надо будет тестировать только на моих магических.
[2014-02-13 11:02:06] select key,val_str,val_number from fly_registry where segment=5
[2014-02-13 11:02:06] select id from fly_dic where name='[loc] Находится на хабе' and dic=5
[2014-02-13 11:02:06] begin;
[2014-02-13 11:02:06] insert into fly_dic (dic,name) values(5,'[loc] Находится на хабе')
[2014-02-13 11:02:06] commit;
много строчек
[2014-02-13 11:07:19] select id from fly_dic where name='[ru] Zolotoy Klyuchik Мирный республика Саха' and dic=5
[2014-02-13 11:07:19] begin;
[2014-02-13 11:07:19] insert into fly_dic (dic,name) values(5,'[ru] Zolotoy Klyuchik Мирный республика Саха')
[2014-02-13 11:07:19] commit;
[2014-02-13 11:07:19] begin;
[2014-02-13 11:07:19] delete from location_db.fly_location_ip
[2014-02-13 11:07:19] insert into location_db.fly_location_ip (start_ip,stop_ip,dic_location,flag_index) values(2130706432,2147483648,1,0)
[2014-02-13 11:07:19] insert into location_db.fly_location_ip (start_ip,stop_ip,dic_location,flag_index) values(167772160,184549376,2,1)
много строчек
[2014-02-13 11:07:26] insert into location_db.fly_location_ip (start_ip,stop_ip,dic_location,flag_index) values(1540024320,1540025344,2389,1416)
[2014-02-13 11:07:26] insert into location_db.fly_location_ip (start_ip,stop_ip,dic_location,flag_index) values(3244974080,3244975104,2389,1416)
[2014-02-13 11:07:26] commit;
основное время тратится на поштучное заполнение "begin; insert into fly_dic (dic,name) values(?,?); commit;"
нужно сделать
begin transaction;
insert into fly_dic (dic,name) values(?,?);
insert into fly_dic (dic,name) values(?,?);
много строчек
insert into fly_dic (dic,name) values(?,?);
insert into fly_dic (dic,name) values(?,?);
commit;
как сделать?
если запись не нашлась по "select id from fly_dic where name='[loc] Находится на хабе' and dic=5" - заносить '[loc] Находится на хабе' во временный массив (вместо непосредственной вставки в базу)
потом открыть транзакцию, перебрать массив, закрыть транзакцию. и всё, скорость первоначального импорта поднимется по сравнению с текущим просто фантастически, без запуска клиента со специфическими параметрами
Последний раз редактировалось HackFresse 13 фев 2014, 11:37, всего редактировалось 1 раз.
begin; insert into fly_dic (dic,name) values(?,?); commit;
Больше не будет такого инсерта - вечером выложу новую сборку.
HackFresse писал(а):как сделать?
если запись не нашлась по "select id from fly_dic where name='[loc] Находится на хабе' and dic=5" - заносить '[loc] Находится на хабе' во временный массив (вместо непосредственной вставки в базу)
Без вствки в базу нельзя получить ID-шку
т.к. она у меня генерится в sqlite - из sqlite_sequence
вот в этом месте l_Cache_ID = m_flySQLiteDB.insertid();
Перекраивать структуру базы нету смысла, проблема не в базе, а просто в алгоритме работы с ней. Может, где-то что-то внутри неё и можно сделать оптимальней, но пока существенного прироста производительности можно добиться, не меняя ни структуры базы, ни режима работы с ней.
Не только при импорте CustomLocations.ini (импорт этот, кстати, очень даже можно выполнить в фоне после подключения всех хабов и спада первоначальной нагрузки), по дампу sqltrace видны другие проблемные места
Ускорить стоковый (для всех и каждого) клиент, просто добавив обработку записей пачкой.
HackFresse писал(а):i3-2100, 4 гига оперативы, винт TOSHIBA DT01ACA050 500GB 7200 RPM 32MB Cache SATA 6.0Gb/s 3.5" (этот поставлен относительно недавно и совсем не хрустит, как мой террабайтный хитачи). Печаль http://yadi.sk/d/kD6b9EDcHoqH6
HackFresse писал(а):вставить пачку, выбрать пачку, пробежаться по полученному массиву для получения id
У меня таблица fly_dic - общий справочник разделенных полем DIC в него пишут с разных потоков
подобный алгоритм будет мудренный или нужно на долгое время лочить поток
я вообще отказался от этой таблицы - экономия от нормлаизации всего 1 мег диска.
+ загрузка быстрее будет - это тоже бонус.
Раньше я вытаскивал название провайдера с подзапросом через внешний ключ dic_location:
select (select name from fly_dic where id = dic_location),start_ip,stop_ip,flag_index
from location_db.fly_location_ip where start_ip <= ? and stop_ip > ? limit 1
найти различия с полученным из *.ini, вставить пачкой в базу недостающие записи, потом снова взять весь массив с локациями их ID
обработка будет быстрой и ненапряжной как для проца, так и для диска
Если при новой структуре базы где-то дальше выборка будет быстрее - конечно, хорошо, если она действительно будет быстрее.
Нужно замерять. И насколько такие запросы частые? выборка у sqlite быстрая, для "редких" операций заморачиваться не стоит, имхо
Но корректно поменять структуру базу у многих юзеров довольно непросто, по сравнению со сменой кода самого приложения
ну да, если старые колонки не удалять, то и проблемы не будет, всего-то не удалось определить какую-то локацию по IP. после добавления колонок убить дату последнего импорта, чтобы инициировать заполнение..
Проблемы не только с файлом CustomLocations.ini (он меняется очень редко, если база заполнена - задержки небольшие). На нем просто наиболее красочно проявилась проблема поштучной записи. В логах и дампе sql-запросов видны проблемы при работе с кучей хабов и при запуске команды на останов ядра, самое мое первое сообщение о проблеме с логамиСпойлер
HackFresse писал(а):flylinkdc писал(а):Если запустить флай с кеем FlylinkDC.exe /sqltrace
[2014-02-11 20:23:29] begin;
[2014-02-11 20:23:29] insert or replace into user_db.user_info (nick,dic_hub,message_count) values('Джек-Потрошитель',2546,1)
[2014-02-11 20:23:29] commit;
[2014-02-11 20:23:29] begin;
[2014-02-11 20:23:29] insert or replace into user_db.user_info (nick,dic_hub,message_count) values('MAFIA',2546,1)
[2014-02-11 20:23:29] commit;
[2014-02-11 20:23:29] begin;
[2014-02-11 20:23:29] insert or replace into user_db.user_info (nick,dic_hub,message_count) values('Admin',2544,2)
[2014-02-11 20:23:29] commit;
[2014-02-11 20:23:30] begin;
[2014-02-11 20:23:30] insert or replace into user_db.user_info (nick,dic_hub,message_count) values('Commfort',2541,1)
[2014-02-11 20:23:30] commit;
Т.е. проблемная работа со словарём будет везде, где используется словарь и поштучная запись, не только 5-й справочник с локациями.
Проблемная работа (тормоза) будет везде, где выполняется любая поштучная запись инфы (о юзерах, хабах и чего-то еще).
Переделывать нужно много в каких местах, простым перестроением базы сделать что-то будет сложно.
select id from fly_dic where name='dchub://gepard-hub.ru' and dic=1
Справочник номер 1 это хабы и там не должно быть так много инсертов.
даже если я сижу на 500 хабах - инсертов будет при первом старте всего 500.
т.к. они редко меняются потом буду всегда лиш select-ы
user_db.user_info - это отдельная таблица туда пишется инфа тоже не массово а только для тех кто что-то сказал
или если у него изменился IP-адрес
Можно на таймере сканировать всех юзеров и определять какие из них стали грязные - скидывать пакетом в базу (напрмиер раз в минуту).
У тебя ведь тормозит при завершении?
сейчас в момент разрушение юзер сам себя скидывает в базу если он менял состояние (IP адрес или кол-во мессаг)