Skip to content

Commit 6207195

Browse files
author
Abduqodiri Qurbonzoda
committed
Add clarifying comments for halfHeightPersistentMap/Set
1 parent b0ceb6f commit 6207195

File tree

5 files changed

+73
-29
lines changed

5 files changed

+73
-29
lines changed

benchmarks-mpp/src/jvmMain/kotlin/benchmarks/immutableMap/Remove.kt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ open class Remove {
2424

2525
private var keys = listOf<IntWrapper>()
2626
private var persistentMap = persistentMapOf<IntWrapper, String>()
27+
28+
/**
29+
* Expected height of this persistent map is equal to the [persistentMap]'s expected height divided by 2.
30+
* Obtained by removing some entries of the [persistentMap].
31+
*/
2732
private var halfHeightPersistentMap = persistentMapOf<IntWrapper, String>()
2833

2934
@Setup(Level.Trial)
@@ -46,8 +51,7 @@ open class Remove {
4651
}
4752

4853
/**
49-
* Puts `size - entriesForHalfHeight(size)` new entries to a persistent map of size `entriesForHalfHeight(size)`
50-
* that had initially [size] entries.
54+
* Puts `size - halfHeightPersistentMap.size` new entries to the [Remove.halfHeightPersistentMap].
5155
*
5256
* Measures mean time and memory spent per (roughly one) `put` operation.
5357
*
@@ -59,19 +63,19 @@ open class Remove {
5963
var map = halfHeightPersistentMap
6064

6165
repeat(size - halfHeightPersistentMap.size) { index ->
62-
map = map.put(keys[index], "some element")
66+
map = map.put(keys[index], "new value")
6367
}
6468

6569
return map
6670
}
6771

6872
/**
69-
* Iterates keys of a persistent map of size `entriesForHalfHeight(size)` several times until iterating [size] elements.
73+
* Iterates keys of the [Remove.halfHeightPersistentMap] several times until iterating [size] elements.
7074
*
7175
* Measures mean time and memory spent per `iterate` operation.
7276
*
73-
* Expected time: [Iterate.iterateKeys] with [Iterate.size] = `entriesForHalfHeight([size])`
74-
* Expected memory: [Iterate.iterateKeys] with [Iterate.size] = `entriesForHalfHeight([size])`
77+
* Expected time: [Iterate.iterateKeys] with [Iterate.size] = `halfHeightPersistentMap.size`
78+
* Expected memory: [Iterate.iterateKeys] with [Iterate.size] = `halfHeightPersistentMap.size`
7579
*/
7680
@Benchmark
7781
fun iterateKeysAfterRemove(bh: Blackhole) {

benchmarks-mpp/src/jvmMain/kotlin/benchmarks/immutableMap/builder/utils.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ fun persistentMapBuilderPut(
1919

2020
var map = emptyPersistentMap<IntWrapper, String>(implementation)
2121
for (index in 0 until immutableSize) {
22-
map = map.put(keys[index], "some element")
22+
map = map.put(keys[index], "some value")
2323
}
2424

2525
val builder = map.builder()
2626
for (index in immutableSize until keys.size) {
27-
builder[keys[index]] = "some element"
27+
builder[keys[index]] = "some value"
2828
}
2929

3030
return builder

benchmarks-mpp/src/jvmMain/kotlin/benchmarks/immutableMap/utils.kt

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,44 @@ fun <K, V> emptyPersistentMap(implementation: String): PersistentMap<K, V> = whe
2222
fun <K> persistentMapPut(implementation: String, keys: List<K>): PersistentMap<K, String> {
2323
var map = emptyPersistentMap<K, String>(implementation)
2424
for (key in keys) {
25-
map = map.put(key, "some element")
25+
map = map.put(key, "some value")
2626
}
2727
return map
2828
}
2929

30-
private fun entriesForHalfHeight(size: Int): Int {
31-
val branchingFactor = 32
32-
val logBranchingFactor = 5
3330

34-
val approximateHeight = ceil(log(size.toDouble(), branchingFactor.toDouble())).toInt()
35-
return 1 shl ((approximateHeight / 2) * logBranchingFactor)
31+
private const val branchingFactor = 32
32+
private const val logBranchingFactor = 5
33+
34+
private fun expectedHeightOfPersistentMapWithSize(size: Int): Int {
35+
return ceil(log(size.toDouble(), branchingFactor.toDouble())).toInt()
3636
}
3737

38+
/**
39+
* Returns the size of a persistent map whose expected height is
40+
* half of the specified [persistentMap]'s expected height.
41+
*/
42+
private fun sizeForHalfHeight(persistentMap: PersistentMap<*, *>): Int {
43+
val expectedHeight = expectedHeightOfPersistentMapWithSize(persistentMap.size)
44+
return 1 shl ((expectedHeight / 2) * logBranchingFactor)
45+
}
3846

47+
/**
48+
* Returns a new persistent map by removing some entries of the specified [persistentMap].
49+
* The expected height of the returned persistent map is half of the specified [persistentMap]'s expected height.
50+
*
51+
* If the specified [persistentMap] does not maintain its canonical form,
52+
* after removing some entries its actual average height will become bigger then its expected height.
53+
* Thus, many operations on the returned persistent map will be slower.
54+
*/
3955
fun <K> halfHeightPersistentMap(persistentMap: PersistentMap<K, String>, keys: List<K>): PersistentMap<K, String> {
40-
val elementsToLeave = entriesForHalfHeight(persistentMap.size)
56+
val entriesToLeave = sizeForHalfHeight(persistentMap)
57+
58+
val shuffledKeys = keys.shuffled()
4159

4260
var map = persistentMap
43-
repeat(persistentMap.size - elementsToLeave) { index ->
44-
map = map.remove(keys[index])
61+
repeat(persistentMap.size - entriesToLeave) { index ->
62+
map = map.remove(shuffledKeys[index])
4563
}
4664
return map
4765
}

benchmarks-mpp/src/jvmMain/kotlin/benchmarks/immutableSet/Remove.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ open class Remove {
2424

2525
private var elements = listOf<IntWrapper>()
2626
private var persistentSet = persistentSetOf<IntWrapper>()
27+
28+
/**
29+
* Expected height of this persistent set is equal to the [persistentSet]'s expected height divided by 2.
30+
* Obtained by removing some elements of the [persistentSet].
31+
*/
2732
private var halfHeightPersistentSet = persistentSetOf<IntWrapper>()
2833

2934
@Setup(Level.Trial)
@@ -46,8 +51,7 @@ open class Remove {
4651
}
4752

4853
/**
49-
* Adds `size - elementsForHalfHeight(size)` new elements to a persistent set of size `elementsForHalfHeight(size)`
50-
* that had initially [size] elements.
54+
* Adds `size - halfHeightPersistentSet.size` new elements to the [Remove.halfHeightPersistentSet].
5155
*
5256
* Measures mean time and memory spent per (roughly one) `add` operation.
5357
*
@@ -66,12 +70,12 @@ open class Remove {
6670
}
6771

6872
/**
69-
* Iterates elements of a persistent set of size `elementsForHalfHeight(size)` several times until iterating [size] elements.
73+
* Iterates elements of the [Remove.halfHeightPersistentSet] several times until iterating [size] elements.
7074
*
7175
* Measures mean time and memory spent per `iterate` operation.
7276
*
73-
* Expected time: [Iterate.iterate] with [Iterate.size] = `elementsForHalfHeight([size])`
74-
* Expected memory: [Iterate.iterate] with [Iterate.size] = `elementsForHalfHeight([size])`
77+
* Expected time: [Iterate.iterate] with [Iterate.size] = `halfHeightPersistentSet.size`
78+
* Expected memory: [Iterate.iterate] with [Iterate.size] = `halfHeightPersistentSet.size`
7579
*/
7680
@Benchmark
7781
fun iterateAfterRemove(bh: Blackhole) {

benchmarks-mpp/src/jvmMain/kotlin/benchmarks/immutableSet/utils.kt

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,38 @@ fun <E> persistentSetAdd(implementation: String, elements: List<E>): PersistentS
2727
return set
2828
}
2929

30-
private fun elementsForHalfHeight(size: Int): Int {
31-
val branchingFactor = 32
32-
val logBranchingFactor = 5
30+
private const val branchingFactor = 32
31+
private const val logBranchingFactor = 5
3332

34-
val approximateHeight = ceil(log(size.toDouble(), branchingFactor.toDouble())).toInt()
35-
return 1 shl ((approximateHeight / 2) * logBranchingFactor)
33+
private fun expectedHeightOfPersistentSetWithSize(size: Int): Int {
34+
return ceil(log(size.toDouble(), branchingFactor.toDouble())).toInt()
3635
}
3736

37+
/**
38+
* Returns the size of a persistent set whose expected height is
39+
* half of the specified [persistentSet]'s expected height.
40+
*/
41+
private fun sizeForHalfHeight(persistentSet: PersistentSet<*>): Int {
42+
val expectedHeight = expectedHeightOfPersistentSetWithSize(persistentSet.size)
43+
return 1 shl ((expectedHeight / 2) * logBranchingFactor)
44+
}
45+
46+
/**
47+
* Returns a new persistent set by removing some elements of the specified [persistentSet].
48+
* The expected height of the returned persistent set is half of the specified [persistentSet]'s expected height.
49+
*
50+
* If the specified [persistentSet] does not maintain its canonical form,
51+
* after removing some elements its actual average height will become bigger then its expected height.
52+
* Thus, many operations on the returned persistent set will be slower.
53+
*/
3854
fun <E> halfHeightPersistentSet(persistentSet: PersistentSet<E>, elements: List<E>): PersistentSet<E> {
39-
val elementsToLeave = elementsForHalfHeight(persistentSet.size)
55+
val elementsToLeave = sizeForHalfHeight(persistentSet)
56+
57+
val shuffledElements = elements.shuffled()
4058

4159
var set = persistentSet
4260
repeat(persistentSet.size - elementsToLeave) { index ->
43-
set = set.remove(elements[index])
61+
set = set.remove(shuffledElements[index])
4462
}
4563
return set
4664
}

0 commit comments

Comments
 (0)