forked from bytedance/ByteX
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request bytedance#57 from bytedance/yangzhiqian/master
merge internal:Cache graph nodes with daemon
- Loading branch information
Showing
24 changed files
with
284 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
common/src/main/java/com/ss/android/ugc/bytex/common/graph/EditableGraph.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.ss.android.ugc.bytex.common.graph | ||
|
||
import java.util.concurrent.ConcurrentHashMap | ||
|
||
/** | ||
* Created by yangzhiqian on 2020/9/3<br/> | ||
*/ | ||
internal class EditableGraph(map: Map<String, Node>) : Graph(map) { | ||
/** | ||
* clear graph info | ||
* called by internal,please do not call. | ||
*/ | ||
fun clear() { | ||
nodeMap = ConcurrentHashMap() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 4 additions & 4 deletions
8
...mon/graph/cache/AsynchronousGraphCache.kt → ...ph/cache/AsynchronousGraphCacheStorage.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,19 @@ | ||
package com.ss.android.ugc.bytex.common.graph.cache | ||
|
||
import com.ss.android.ugc.bytex.common.graph.Graph | ||
import com.ss.android.ugc.bytex.common.graph.Node | ||
import com.ss.android.ugc.bytex.transformer.concurrent.Schedulers | ||
import java.util.concurrent.Future | ||
|
||
/** | ||
* Created by yangzhiqian on 2020/7/12<br/> | ||
*/ | ||
class AsynchronousGraphCache<T>(realCache: IGraphCache<T>) : IGraphCache<T> by realCache { | ||
internal class AsynchronousGraphCacheStorage<T>(realCacheStorage: GraphCacheStorage<T>) : GraphCacheStorage<T> by realCacheStorage { | ||
|
||
fun loadCacheAsync(t: T?, graphBuilder: CachedGraphBuilder): Future<Boolean> { | ||
return Schedulers.IO().submit { loadCache(t, graphBuilder) } | ||
} | ||
|
||
fun saveCacheAsync(t: T?, graph: Graph): Future<Boolean> { | ||
return Schedulers.IO().submit { saveCache(t, graph) } | ||
fun saveCacheAsync(t: T?, nodes: Map<String, Node>): Future<Boolean> { | ||
return Schedulers.IO().submit { saveCache(t, nodes) } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
128 changes: 93 additions & 35 deletions
128
common/src/main/java/com/ss/android/ugc/bytex/common/graph/cache/CachedGraphBuilder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,122 @@ | ||
package com.ss.android.ugc.bytex.common.graph.cache; | ||
|
||
import com.ss.android.ugc.bytex.common.configuration.BooleanProperty | ||
import com.ss.android.ugc.bytex.common.graph.Graph | ||
import com.ss.android.ugc.bytex.common.graph.GraphBuilder | ||
import com.ss.android.ugc.bytex.common.graph.* | ||
import java.io.File | ||
import java.util.concurrent.Future | ||
import java.util.* | ||
import java.util.concurrent.ConcurrentHashMap | ||
|
||
class CachedGraphBuilder(private val graphCacheFile: File?, shouldLoadCache: Boolean, private val shouldSaveCache: Boolean) : GraphBuilder() { | ||
private val graphCache = | ||
AsynchronousGraphCache( | ||
DefaultGraphCache( | ||
GsonClassesCache( | ||
if (BooleanProperty.ENABLE_RAM_CACHE.value()) { | ||
RAMClassesCache | ||
AsynchronousGraphCacheStorage( | ||
DefaultGraphCacheStorage( | ||
if (BooleanProperty.ENABLE_RAM_CACHE.value() && BooleanProperty.ENABLE_RAM_NODES_CACHE.value()) { | ||
RamNodeCacheStorage | ||
} else { | ||
null | ||
}, | ||
GsonFileClassCacheStorage( | ||
if (BooleanProperty.ENABLE_RAM_CACHE.value() && BooleanProperty.ENABLE_RAM_CLASSES_CACHE.value()) { | ||
RamClassesCacheStorage | ||
} else { | ||
null | ||
} | ||
) | ||
) | ||
) | ||
private var grapCacheFuture: Future<Boolean>? = null | ||
private val isCacheValid = | ||
shouldLoadCache && | ||
if (BooleanProperty.ENABLE_ASYNC_LOAD_CACHE.value()) { | ||
grapCacheFuture = graphCache.loadCacheAsync(graphCacheFile, this) | ||
true | ||
} else { | ||
graphCache.loadCache(graphCacheFile, this).apply { | ||
graphCacheFile?.delete() | ||
if (graphCacheFile != null) { | ||
RAMClassesCache.clearCache(graphCacheFile) | ||
} | ||
if (!this) { | ||
throw IllegalStateException("Failed to load cache") | ||
} | ||
} | ||
try { | ||
shouldLoadCache && graphCache.loadCache(graphCacheFile, this).apply { | ||
if (!this) { | ||
RamClassesCacheStorage.clear() | ||
RamNodeCacheStorage.clear() | ||
graphCacheFile?.delete() | ||
throw IllegalStateException("Failed to load cache") | ||
|
||
} | ||
} | ||
} finally { | ||
if (graphCacheFile != null) { | ||
graphCacheFile.delete() | ||
RamClassesCacheStorage.clearCache(graphCacheFile) | ||
RamNodeCacheStorage.clearCache(graphCacheFile) | ||
} | ||
} | ||
|
||
|
||
override fun isCacheValid(): Boolean = isCacheValid | ||
|
||
@Synchronized | ||
override fun build(): Graph { | ||
//先保证cache执行完成 | ||
grapCacheFuture?.get()?.apply { | ||
graphCacheFile?.delete() | ||
if (graphCacheFile != null) { | ||
RAMClassesCache.clearCache(graphCacheFile) | ||
} | ||
if (!this) { | ||
throw IllegalStateException("Failed to load cache") | ||
/** | ||
* from cache during incremental build | ||
*/ | ||
internal fun addNodes(nodes: Map<String, Node>) { | ||
//during incremental build, the classes which changed will be added again, and the calculation of the inheritance | ||
//relationship will be repeated. Replace it with a de-duplicated list here | ||
//增量时,原先的class changd会导致被add两次,计算继承关系会重复,这里替换成去重的list | ||
for (node in nodes.values) { | ||
if (node is ClassNode) { | ||
if (node.children.isNotEmpty() && node.children !is SkipDuplicatedList) { | ||
node.children = SkipDuplicatedList(node.children) | ||
} | ||
} else if (node is InterfaceNode) { | ||
if (node.children.isNotEmpty() && node.children !is SkipDuplicatedList) { | ||
node.children = SkipDuplicatedList(node.children) | ||
} | ||
if (node.implementedClasses.isNotEmpty() && node.implementedClasses !is SkipDuplicatedList) { | ||
node.implementedClasses = SkipDuplicatedList(node.implementedClasses) | ||
} | ||
} | ||
} | ||
if (nodeMap.isEmpty() && nodes is ConcurrentHashMap) { | ||
//减少复制 | ||
nodeMap = nodes | ||
} else { | ||
nodeMap.putAll(nodes) | ||
} | ||
} | ||
|
||
@Synchronized | ||
override fun build(): Graph { | ||
val graph = super.build() | ||
if (shouldSaveCache) { | ||
if (BooleanProperty.ENABLE_ASYNC_SAVE_CACHE.value()) { | ||
graphCache.saveCacheAsync(graphCacheFile, graph) | ||
graphCache.saveCacheAsync(graphCacheFile, nodeMap) | ||
} else { | ||
graphCache.saveCache(graphCacheFile, graph) | ||
graphCache.saveCache(graphCacheFile, nodeMap) | ||
} | ||
} | ||
return graph | ||
} | ||
|
||
|
||
internal class SkipDuplicatedList<T>(c: Collection<T>) : LinkedList<T>(c) { | ||
|
||
override fun add(element: T): Boolean { | ||
if (contains(element)) { | ||
return false | ||
} | ||
return super.add(element) | ||
} | ||
|
||
override fun add(index: Int, element: T) { | ||
if (contains(element)) { | ||
return | ||
} | ||
super.add(index, element) | ||
} | ||
|
||
override fun addFirst(element: T) { | ||
if (contains(element)) { | ||
return | ||
} | ||
super.addFirst(element) | ||
} | ||
|
||
override fun addLast(element: T) { | ||
if (contains(element)) { | ||
return | ||
} | ||
super.addLast(element) | ||
} | ||
} | ||
} |
Oops, something went wrong.