Utworzyłem 1 milion węzłów Neo4j w partiach po 10000, każda partia we własnej transakcji. Dziwne jest to, że zrównoleglenie tego procesu z wykonywaniem wielowątkowym nie miało żadnego pozytywnego wpływu na wydajność. To tak, jakby transakcje w różnych wątkach blokowały się nawzajem.
Oto fragment kodu Scali, który testuje to za pomocą równoległych kolekcji:
import org.neo4j.kernel.EmbeddedGraphDatabase
object Main extends App {
val total = 1000000
val batchSize = 10000
val db = new EmbeddedGraphDatabase("neo4yay")
Runtime.getRuntime().addShutdownHook(
new Thread(){override def run() = db.shutdown()}
)
(1 to total).grouped(batchSize).toSeq.par.foreach(batch => {
println("thread %s, nodes from %d to %d"
.format(Thread.currentThread().getId, batch.head, batch.last))
val transaction = db.beginTx()
try{
batch.foreach(db.createNode().setProperty("Number", _))
}finally{
transaction.finish()
}
})
}
A oto wiersze build.sbt
potrzebne do zbudowania i uruchomienia go:
scalaVersion := "2.9.2"
libraryDependencies += "org.neo4j" % "neo4j-kernel" % "1.8.M07"
fork in run := true
Można przełączać się między trybami równoległymi i sekwencyjnymi, usuwając i dodając wywołanie .par
przed zewnętrznym foreach
. Dane wyjściowe konsoli wyraźnie pokazują, że wykonanie .par
jest rzeczywiście wielowątkowe.
Aby wykluczyć możliwe problemy ze współbieżnością w tym kodzie, wypróbowałem również implementację opartą na aktorach, z mniej więcej takim samym wynikiem (odpowiednio 6 i 7 sekund dla wersji sekwencyjnej i równoległej).
Więc pytanie brzmi: czy zrobiłem coś źle, czy to jest ograniczenie Neo4j? Dziękuję!
2 odpowiedzi
Głównym problemem jest to, że twój tx dociera mniej więcej w tym samym czasie. A zatwierdzenia transakcji to serializowane zapisy w dzienniku transakcji. Jeśli zapisy byłyby przeplatane w czasie, a rzeczywiste tworzenie węzła byłoby droższym procesem, przyspieszyłoby to.
Wstawianie wsadowe nie działa z wieloma gwintami. Z dokumentacji neo4j:
Zawsze wykonuj wstawianie wsadowe w jednym wątku (lub używaj synchronizacji, aby tylko jeden wątek naraz miał dostęp do programu wsadowego) i wywołaj zamknięcie po zakończeniu.
Podobne pytania
Nowe pytania
scala
Scala to język programowania ogólnego przeznaczenia, którego głównym celem jest wirtualna maszyna Java. Zaprojektowany, aby wyrazić powszechne wzorce programowania w zwięzły, elegancki i bezpieczny sposób, łączy zarówno imperatywne, jak i funkcjonalne style programowania. Jego kluczowe cechy to: zaawansowany system typów statycznych z wnioskiem o typie; typy funkcji; dopasowywanie wzorców; niejawne parametry i konwersje; przeciążenie operatora; pełna interoperacyjność z Javą; konkurencja