neo4j 4.3.3 apoc.periodic.iterate использует только одно ядро : как работает параллелизм параметров?

#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 поток