Skip to content

Commit

Permalink
Merge pull request #457 from handymenny/optimize
Browse files Browse the repository at this point in the history
Optimize space occupied by cache
  • Loading branch information
handymenny authored Aug 2, 2024
2 parents aa9ac86 + b55c0eb commit 85d6caf
Showing 3 changed files with 63 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -55,5 +55,5 @@ object HelpMessage {
const val CUSTOM_CSS = "Inject custom css in Web UI"
const val CUSTOM_JS = "Inject custom js in Web UI"
const val LIBRARY_CACHE =
"Number of items to cache, each items occupies ~0.15MB of RAM. 0 = disabled, -1 = unlimited."
"Number of items to cache, each items occupies ~4-80KB of RAM. 0 = disabled, -1 = unlimited."
}
45 changes: 29 additions & 16 deletions src/main/java/it/smartphonecombo/uecapabilityparser/util/Intern.kt
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
package it.smartphonecombo.uecapabilityparser.util

import it.smartphonecombo.uecapabilityparser.model.EmptyMimo
import it.smartphonecombo.uecapabilityparser.model.Mimo
import it.smartphonecombo.uecapabilityparser.model.bandwidth.Bandwidth
import it.smartphonecombo.uecapabilityparser.model.bandwidth.EmptyBandwidth
import it.smartphonecombo.uecapabilityparser.model.modulation.EmptyModulation
import it.smartphonecombo.uecapabilityparser.model.modulation.Modulation
import it.smartphonecombo.uecapabilityparser.model.band.IBandDetails
import it.smartphonecombo.uecapabilityparser.model.combo.ICombo
import it.smartphonecombo.uecapabilityparser.model.component.IComponent

open class InternMap<T>(maxCapacity: Int) {
@Transient private val lock = Any()

private val internalMap: LinkedHashMap<T, T> =
object : LinkedHashMap<T, T>(minOf(16, maxCapacity), 0.75f) {
object : LinkedHashMap<T, T>(computeInitialCapacity(maxCapacity)) {
override fun removeEldestEntry(eldest: Map.Entry<T, T>): Boolean {
return size > maxCapacity
}
}

private fun put(value: T): T {
internalMap[value] = value
synchronized(lock) { internalMap[value] = value }
return value
}

fun intern(value: T): T = internalMap[value] ?: put(value)

fun contains(value: T): Boolean = internalMap.contains(value)

fun size() = internalMap.size

companion object {
private fun computeInitialCapacity(maxCapacity: Int): Int {
// A value that ensures no re-hash is maxCapacity / 0.75 + 1
// Compute that value / 2
val initialCapacity = Math.floorDiv(maxCapacity * 2, 3) + 1

return maxOf(16, initialCapacity)
}
}
}

object MimoInternMap : InternMap<Mimo>(100)
private object IBandDetailsInternMap : InternMap<IBandDetails>(1000)

private object IComponentInternMap : InternMap<IComponent>(10000)

object ModulationInternMap : InternMap<Modulation>(100)
private object IComboInternMap : InternMap<ICombo>(100000)

object BandwidthInternMap : InternMap<Bandwidth>(100)
internal fun IBandDetails.intern() = IBandDetailsInternMap.intern(this)

internal fun Mimo.intern(): Mimo = if (this == EmptyMimo) this else MimoInternMap.intern(this)
internal fun IComponent.intern() = IComponentInternMap.intern(this)

internal fun Modulation.intern() =
if (this == EmptyModulation) this else ModulationInternMap.intern(this)
internal fun ICombo.intern() = IComboInternMap.intern(this)

internal fun Bandwidth.intern() =
if (this == EmptyBandwidth) this else BandwidthInternMap.intern(this)
internal fun ICombo.alreadyInterned() = IComboInternMap.contains(this)
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
package it.smartphonecombo.uecapabilityparser.util

import it.smartphonecombo.uecapabilityparser.extension.trimToSize
import it.smartphonecombo.uecapabilityparser.extension.typedList
import it.smartphonecombo.uecapabilityparser.model.Capabilities
import it.smartphonecombo.uecapabilityparser.model.band.IBandDetails
import it.smartphonecombo.uecapabilityparser.model.combo.ComboEnDc
import it.smartphonecombo.uecapabilityparser.model.combo.ComboLte
import it.smartphonecombo.uecapabilityparser.model.combo.ComboNr
import it.smartphonecombo.uecapabilityparser.model.combo.ComboNrDc
import it.smartphonecombo.uecapabilityparser.model.combo.ICombo
import it.smartphonecombo.uecapabilityparser.model.component.ComponentNr
import it.smartphonecombo.uecapabilityparser.model.component.IComponent

internal fun Capabilities.optimize() {
lteBands.forEach { it.optimize() }
nrBands.forEach { it.optimize() }
lteCombos.forEach { it.optimize() }
nrCombos.forEach { it.optimize() }
nrDcCombos.forEach { it.optimize() }
enDcCombos.forEach { it.optimize() }
}
// bands
lteBands = lteBands.map(IBandDetails::intern).typedList()
nrBands = nrBands.map(IBandDetails::intern).typedList()

internal fun IBandDetails.optimize() {
mimoDL = mimoDL.intern()
mimoUL = mimoUL.intern()
modDL = modDL.intern()
modUL = modUL.intern()
// combos
lteCombos = lteCombos.map(ICombo::optimizeAndIntern).typedList()
nrCombos = nrCombos.map(ICombo::optimizeAndIntern).typedList()
nrDcCombos = nrDcCombos.map(ICombo::optimizeAndIntern).typedList()
enDcCombos = enDcCombos.map(ICombo::optimizeAndIntern).typedList()
}

internal fun ICombo.optimize() {
masterComponents.trimToSize()
masterComponents.forEach { it.optimize() }
secondaryComponents.trimToSize()
secondaryComponents.forEach { it.optimize() }
private fun ICombo.optimizeAndIntern(): ICombo {
val res = if (alreadyInterned()) this else optimized()
return res.intern()
}

internal fun IComponent.optimize() {
mimoDL = mimoDL.intern()
mimoUL = mimoUL.intern()
modDL = modDL.intern()
modUL = modUL.intern()
if (this is ComponentNr) {
maxBandwidthDl = maxBandwidthDl.intern()
maxBandwidthUl = maxBandwidthUl.intern()
private fun ICombo.optimized(): ICombo {
val masterComponentsOpt = masterComponents.map(IComponent::intern)
val secondaryComponentsOpt = secondaryComponents.map(IComponent::intern)

return when (this) {
is ComboLte -> copy(masterComponents = masterComponentsOpt.typedList())
is ComboNr -> copy(masterComponents = masterComponentsOpt.typedList())
is ComboNrDc ->
copy(
masterComponents = masterComponentsOpt.typedList(),
secondaryComponents = secondaryComponentsOpt.typedList(),
)
is ComboEnDc ->
copy(
masterComponents = masterComponentsOpt.typedList(),
secondaryComponents = secondaryComponentsOpt.typedList(),
)
}
}

0 comments on commit 85d6caf

Please sign in to comment.