#neo4j #parallel-processing #neo4j-apoc
Вопрос:
tl;tr:
concurrency
работает по назначению и обеспечивает нам реальный параллелизм, но следите за конфигурацией JVM в среде docker
При просмотре документов apoc.periodic.iterate есть параметр concurrency
В документах этот параметр объясняется следующим образом:
количество параллельных задач генерируется при использовании parallel:true
Поэтому при выполнении следующего кода (на машине с 64 простаивающими ядрами):
CALL apoc.periodic.iterate(
"UNWIND range(1, 10) AS x RETURN x",
"CALL apoc.util.sleep(1000) RETURN 0",
{
batchSize: 1,
parallel: true,
concurrency: 10
}
)
Я бы ожидал, что время выполнения составит ~1 секунду. Но у меня есть 10 секунд
Мое ожидание таково: у нас есть 10 «партий». Каждая партия должна спать 1 секунду. Все 10 пакетов должны работать параллельно.
Мои ожидания неверны или Neo4j/apoc ошибочны?
Я знаю, что есть разница между «параллелизмом» и «параллелизмом». В документах neo4j не совсем ясно, что здесь происходит, и смешивание двух терминов в одной функции. Так, может быть, у нас действительно нет реального параллелизма с apoc.periodic.iterate
? Если мы этого не сделаем, есть ли альтернатива реальному параллелизму (только с помощью шифра)?
Спасибо за любые подсказки!
ОБНОВЛЕНИЕ № 1 Добавлены журналы:
Это то, что показывают журналы (уровень: отладка)
2021-08-25 09:32:28.282 0000 INFO [o.n.k.a.p.GlobalProcedures] starting batching from `UNWIND range(1, 10) AS x RETURN x` operation using iteration `CALL apoc.util.sleep(1000) RETURN 0` in separate thread
2021-08-25 09:32:28.282 0000 DEBUG [o.n.k.a.p.GlobalProcedures] execute in batch no 1 batch size
2021-08-25 09:32:28.283 0000 DEBUG [o.n.k.a.p.GlobalProcedures] execute in batch no 1 batch size
2021-08-25 09:32:28.283 0000 DEBUG [o.n.k.a.p.GlobalProcedures] execute in batch no 1 batch size
2021-08-25 09:32:28.283 0000 DEBUG [o.n.k.a.p.GlobalProcedures] execute in batch no 1 batch size
2021-08-25 09:32:28.283 0000 DEBUG [o.n.k.a.p.GlobalProcedures] execute in batch no 1 batch size
2021-08-25 09:32:28.283 0000 DEBUG [o.n.k.a.p.GlobalProcedures] execute in batch no 1 batch size
2021-08-25 09:32:28.283 0000 DEBUG [o.n.k.a.p.GlobalProcedures] execute in batch no 1 batch size
2021-08-25 09:32:28.283 0000 DEBUG [o.n.k.a.p.GlobalProcedures] execute in batch no 1 batch size
2021-08-25 09:32:28.283 0000 DEBUG [o.n.k.a.p.GlobalProcedures] execute in batch no 1 batch size
2021-08-25 09:32:28.283 0000 DEBUG [o.n.k.a.p.GlobalProcedures] execute in batch no 1 batch size
Результат таков
╒═════════╤═══════╤═══════════╤═════════════════════╤══════════════════╤═══════════════╤═════════╤═══════════════╤══════════════════════════════════════════════════╤══════════════════════════════════════════════════╤═══════════════╤══════════════╤══════════════════════════════════════════════════════════════════════╕
│"batches"│"total"│"timeTaken"│"committedOperations"│"failedOperations"│"failedBatches"│"retries"│"errorMessages"│"batch" │"operations" │"wasTerminated"│"failedParams"│"updateStatistics" │
╞═════════╪═══════╪═══════════╪═════════════════════╪══════════════════╪═══════════════╪═════════╪═══════════════╪══════════════════════════════════════════════════╪══════════════════════════════════════════════════╪═══════════════╪══════════════╪══════════════════════════════════════════════════════════════════════╡
│10 │10 │10 │10 │0 │0 │0 │{} │{"total":10,"committed":10,"failed":0,"errors":{}}│{"total":10,"committed":10,"failed":0,"errors":{}}│false │{} │{"nodesDeleted":0,"labelsAdded":0,"relationshipsCreated":0,"nodesCreat│
│ │ │ │ │ │ │ │ │ │ │ │ │ed":0,"propertiesSet":0,"relationshipsDeleted":0,"labelsRemoved":0} │
└─────────┴───────┴───────────┴─────────────────────┴──────────────────┴───────────────┴─────────┴───────────────┴──────────────────────────────────────────────────┴──────────────────────────────────────────────────┴───────────────┴──────────────┴────────────────
ОБНОВЛЕНИЕ No2 Обнаружило причину и исправление:
Я предполагаю, что проблема связана со странным поведением виртуальной машины Java в сочетании с моими k8.
Я создал java-скрипт внутри своего контейнера Neo4j:
public class Main {
public static void main(String[] args) {
System.out.println("Runtime.getRuntime().availableProcessors() = "
Runtime.getRuntime().availableProcessors());
}
}
Этот скрипт вернул, что Java видит только 1 ядро:
root@neo4j02-prod-5476cd65ff-2wdgk:/tmp# java -cp . main.java
Runtime.getRuntime().availableProcessors() = 1
Я мог бы исправить это с помощью опции jvm -XX:ActiveProcessorCount=60
root@neo4j02-prod-5476cd65ff-2wdgk:/tmp# java -XX:ActiveProcessorCount=60 -cp . main.java
Runtime.getRuntime().availableProcessors() = 60
Это стало для меня доказательством того, что JVM в образе докера Neo4j по умолчанию в некоторых случаях не может обеспечить правильное количество ядер.
На данный момент я могу исправить это, передав NEO4J_dbms_jvm_additional=-XX:ActiveProcessorCount=60
as ENVvar в мой контейнер neo4j.
Теперь возникает вопрос, существует ли для этого не закодированное решение?
Комментарии:
1. Вы проверили свои журналы? (neo4j.log и debug.log) вы можете узнать, создает ли algo там 10 потоков (это показывает что — то вроде-имя algo количество потоков)
2. Нет, в журналах просто говорится в один момент, что все пакеты обработаны. но полученное время показывает обратное. кстати: В БД доступно 64 ядра процессора
3. О, просто кое-что заметил. Почему вы передаете размер пакета:1? Вы определенно должны включить это, например, МНОГО, может быть, 100, 1000, 10000. Также параллелизм по умолчанию равен 50, нет необходимости устанавливать его ниже
4. НоНоНо, это неправильно. Размер пакета — это количество объектов, взятых из верхнего запроса. если бы я ввел размер пакета 10, я бы определенно получил только 1 поток