В моем проекте я использую spring-data-neo4j 4.2.0.M1 с neo4j-ogm 2.0.4. Первоначально это использовало встроенный экземпляр neo4j, но в ходе исследования по этой проблеме я перешел на выделенный экземпляр neo4j (работающий на той же машине, хотя), используя протокол Bolt.Neo4j-ogm: Уменьшение производительности записи/сопоставления
Я постоянно вставляю данные, в основном, поскольку он становится доступным для моего приложения (поэтому я не могу использовать пакетную вставку). После запуска это отлично работает и сохранение экземпляра моего NodeEntity занимает ~ 60 мс, что отлично подходит для моего использования. Однако это медленно ухудшается с течением времени. Через 10-20 минут это замедляется примерно до 2 с за сохранение, что уже не так здорово. Время, похоже, здесь достигает максимума и не уменьшается намного больше.
Первоначально я предполагал, что это было вызвано слишком маленьким внедренным экземпляром, так как я видел повторяющиеся сообщения о приостановках GC, сообщаемых neo4j. Затем я перешел на выделенный экземпляр, который намного больше, и эти предупреждения GC больше не отображаются. Однако деградация все же происходит.
размеры магазина, как сообщает Neo4j:
Array Store 8.00 KiB
Logical Log 151.36 MiB
Node Store 40.14 MiB
Property Store 1.83 GiB
Relationship Store 742.63 MiB
String Store> Size 120.87 MiB
Total Store Size 4.55 GiB
Экземпляр является конфигурирует следующим образом: (! Режим сэмплера)
dbms.memory.pagecache.size=5g
dbms.memory.heap.initial_size=4g
dbms.memory.heap.max_size=4g
dbms.jvm.additional=-XX:+UseG1GC
Использование YourKit профилировщика я могу видеть, что большую часть времени, кажется, расходоваться EntityGraphMapper Neo4j-OGM, в частности, в
org.neo4j.ogm.context.EntityGraphMapper#haveRelationEndsChanged
Сохранение NodeEntity обычно имеет около 40 связей с другими узлами, большинство из которых моделируется как RelationshipEntity. На более ранней стадии я уже заметил, что сохранение объектов было довольно медленным, так как были отображены слишком много связанных (но неизменных) объектов. С тех пор я использую глубину 1 при сохранении. Непрерывные операции, которые приводят к сохранению NodeEntitites, используют размер транзакции 200 объектов.
Я еще не уверен, что neo4j-ogm на самом деле является причиной замедления, так как я не вижу, какие изменения по сравнению с хорошими исходными результатами. В таких случаях я обычно подозреваю утечку памяти/загрязнение, но все результаты мониторинга для этого хорошо выглядят в моем приложении. Для экземпляра сервера neo4j я не знаю, где искать такую информацию, кроме debug.log.
В общем, я потратил довольно много времени на изучение этого и не знаю, что еще посмотреть. Любые мысли или предложения? Я рад предоставить дополнительную информацию.
Edit: Follwing @ вход Винса, я был еще раз взглянуть на распределение памяти и обнаружил, что на самом деле Neo4jSession вырос довольно много после того, позволяя запустить приложение в течение ~ 3 часов:
В то время куча была 1,7 ГБ большой, из которых 70% ссылались на живые данные. Из этого в настоящее время упоминается (и поддерживается) около 300 МБ Neo4jSession. Это может означать, что оно стало слишком большим. Как я могу вмешаться вручную здесь?
Вы создаете новый сеанс для каждой транзакции (партия из 200 объектов) или используете один сеанс? – Vince
Я использую ту же сессию (я думаю). У меня нет ручного управления сессиями, а также использование области по умолчанию. Из того, что я понял из документации, это должно быть полезно для многих более длительных операций? Тем не менее, я не ожидаю обновлений за пределами рабочего потока. – geld0r
Существа придерживаются в сессии, пока не получат сбор мусора. Может быть какое-то влияние на производительность в 'hasRelationEndsChanged', если вы загружаете много тысяч объектов, поэтому может стоить делать' session.clear() 'между каждой транзакцией и посмотреть, поможет ли это. – Vince