-
Notifications
You must be signed in to change notification settings - Fork 84
Open
Description
Hey Neal!
I am investigating performance. So I've added 100_000 entries into my ldap server.
The aim is - to read 10_000 entries from ldap server(I use different size batches for that)
- Using async api and independent LdapConnections (size is 20)
- Using async api and LdapConnection from LdapConnectionPool(size is 20)
Let me provide peaces of code:
case 1:
@ParameterizedTest
@EnumSource(BatchSize::class)
fun getByBatchAsyncBasicListener(batchSize: BatchSize) {
val areWholeBatches = ENTRY_COUNT % batchSize.size == 0
val batchCount = if (areWholeBatches) {
ENTRY_COUNT / batchSize.size
} else {
ENTRY_COUNT / batchSize.size + 1
}
val entries = HashSet<SearchResultEntry>()
IntRange(0, batchCount - 1).map { batchIndex ->
IntRange(1, batchSize.size)
.filter { entryIndex -> entryIndex + (batchIndex * batchSize.size) <= ENTRY_COUNT }
.map { entryIndex ->
getEntryDn(entryIndex + (batchIndex * batchSize.size))
}.let { idList ->
getEntriesBatchAsync(baseSearchDn, idList)
}
}.map { (asyncRequestId, listener) ->
asyncRequestId.get()
entries.addAll(listener.searchEntries)
}
}
fun getEntriesBatchAsync(
baseDn: String,
dns: List<String>,
vararg attributes: String,
): Pair<AsyncRequestID, BasicAsyncSearchResultListener> {
val resultListener = BasicAsyncSearchResultListener()
val searchRequest = SearchRequest(
resultListener,
baseDn,
SearchScope.ONE,
DereferencePolicy.NEVER,
0,
0,
false,
getIdsFilter(dns),
*attributes,
)
val asyncSearch = getConnection().asyncSearch(searchRequest)
return Pair(asyncSearch, resultListener)
}
some details about getConnection():
At this case I create up to 20 connections and return them in random manner.
The result is:
case 2:
@ParameterizedTest
@EnumSource(BatchSize::class)
fun getByBatchAsyncBasicListenerConnectionPoolNew(batchSize: BatchSize) {
require(ENTRY_COUNT > batchSize.size)
val areWholeBatches = ENTRY_COUNT % batchSize.size == 0
val batchCount = if (areWholeBatches) {
ENTRY_COUNT / batchSize.size
} else {
ENTRY_COUNT / batchSize.size + 1
}
val entries = HashSet<SearchResultEntry>()
try {
IntRange(0, batchCount - 1).map { batchIndex ->
IntRange(1, batchSize.size)
.filter { entryIndex -> entryIndex + (batchIndex * batchSize.size) <= ENTRY_COUNT }
.map { entryIndex ->
getEntryDn(entryIndex + (batchIndex * batchSize.size))
}.let { idsBatch ->
getEntriesBatchAsyncPoolNew(baseSearchDn, idsBatch)
}
}.flatMap { (asyncReq, listener) ->
asyncReq.get()
listener.searchEntries
}.let { result -> entries.addAll(result) }
}
fun getEntriesBatchAsyncPoolNew(
baseDn: String,
dns: List<String>,
vararg attributes: String,
): Pair<AsyncRequestID, BasicAsyncSearchResultListener> =
SearchRequest(
BasicAsyncSearchResultListener(),
baseDn,
SearchScope.ONE,
DereferencePolicy.NEVER,
0,
0,
false,
getIdsFilter(dns),
*attributes,
)
.let { searchReq ->
getConnectionPool().processRequestsAsync(listOf(searchReq), -1)
.map { asyncRequestID ->
Pair(asyncRequestID, searchReq.searchResultListener as BasicAsyncSearchResultListener)
}[0]
}
at this case getConnectionPool() returns the same object of type LDAPConnectionPool which is created like this:
val startTLSPostConnectProcessor = StartTLSPostConnectProcessor(SSLUtil(TrustAllTrustManager()).createSSLContext())
val ldapConnectionPool = LDAPConnectionPool(exampleConnection, 1, 20, startTLSPostConnectProcessor)
ldapConnectionPool.setBindRequest(simpleBindRequest)
I tried to make Thread dump during test run and I see a lot of Reader Threads. Maybe it could help ti understand the root cause.


As you can see LDAPConnectionPool make performance much worse.
Do I use API in a wrong way ? is there way to improve that ?
Metadata
Metadata
Assignees
Labels
No labels

