core: Make topological sort more efficient

This commit is contained in:
Andras Slemmer 2016-09-08 10:04:18 +01:00
parent d6f82637ad
commit 5596ced5c3

View File

@ -33,40 +33,36 @@ class ResolveTransactionsProtocol(private val txHashes: Set<SecureHash>,
companion object { companion object {
private fun dependencyIDs(wtx: WireTransaction) = wtx.inputs.map { it.txhash }.toSet() private fun dependencyIDs(wtx: WireTransaction) = wtx.inputs.map { it.txhash }.toSet()
private fun topologicalSort(transactions: Iterable<SignedTransaction>): List<SignedTransaction> { private fun topologicalSort(transactions: Collection<SignedTransaction>): List<SignedTransaction> {
// Construct txhash -> dependent-txhashes map // Construct txhash -> dependent-txhashes map
val forwardGraph = HashMap<SecureHash, HashSet<SecureHash>>() val forwardGraph = HashMap<SecureHash, HashSet<SignedTransaction>>()
transactions.forEach { tx -> transactions.forEach { tx ->
tx.tx.inputs.forEach { input -> tx.tx.inputs.forEach { input ->
forwardGraph.getOrPut(input.txhash) { HashSet() }.add(tx.id) forwardGraph.getOrPut(input.txhash) { HashSet() }.add(tx)
} }
} }
// Construct txhash -> tx map val visited = HashSet<SecureHash>(transactions.size)
val transactionMap = HashMap<SecureHash, SignedTransaction>() val result = ArrayList<SignedTransaction>(transactions.size)
transactions.forEach { transactionMap[it.tx.id] = it }
val visited = HashSet<SecureHash>() fun visit(transaction: SignedTransaction) {
val result = LinkedList<SignedTransaction>() if (transaction.id in visited) {
fun visit(transactionHash: SecureHash) {
if (transactionHash in visited) {
return return
} }
visited.add(transactionHash) visited.add(transaction.id)
forwardGraph[transactionHash]?.forEach { forwardGraph[transaction.id]?.forEach {
visit(it) visit(it)
} }
result.addFirst(transactionMap[transactionHash]!!) result.add(transaction)
} }
transactions.forEach { transactions.forEach {
visit(it.tx.id) visit(it)
} }
require(result.size == transactionMap.size) require(result.size == transactions.size)
require(visited.size == transactionMap.size) result.reverse()
return result return result
} }
@ -134,7 +130,7 @@ class ResolveTransactionsProtocol(private val txHashes: Set<SecureHash>,
override val topic: String get() = throw UnsupportedOperationException() override val topic: String get() = throw UnsupportedOperationException()
@Suspendable @Suspendable
private fun downloadDependencies(depsToCheck: Set<SecureHash>): List<SignedTransaction> { private fun downloadDependencies(depsToCheck: Set<SecureHash>): Collection<SignedTransaction> {
// Maintain a work queue of all hashes to load/download, initialised with our starting set. Then do a breadth // Maintain a work queue of all hashes to load/download, initialised with our starting set. Then do a breadth
// first traversal across the dependency graph. // first traversal across the dependency graph.
// //
@ -184,7 +180,7 @@ class ResolveTransactionsProtocol(private val txHashes: Set<SecureHash>,
throw ExcessivelyLargeTransactionGraph() throw ExcessivelyLargeTransactionGraph()
} }
return resultQ.values.reversed() return resultQ.values
} }
/** /**