-
-
Notifications
You must be signed in to change notification settings - Fork 213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perf: Execute patches in parallel #321
Changes from 3 commits
57620fd
ce57c4f
d33f199
07c3ae4
708e91e
2ecec37
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,28 +2,32 @@ package app.revanced.patcher.util | |
|
||
import app.revanced.patcher.util.proxy.ClassProxy | ||
import com.android.tools.smali.dexlib2.iface.ClassDef | ||
import java.util.* | ||
|
||
/** | ||
* A list of classes and proxies. | ||
* | ||
* @param classes The classes to be backed by proxies. | ||
*/ | ||
class ProxyClassList internal constructor(classes: MutableList<ClassDef>) : MutableList<ClassDef> by classes { | ||
internal val proxyPool = mutableListOf<ClassProxy>() | ||
class ProxyClassList internal constructor(classes: MutableList<ClassDef>) : MutableList<ClassDef> by Collections.synchronizedList(classes) { | ||
internal val proxyPool = Collections.synchronizedList(mutableListOf<ClassProxy>()) | ||
|
||
/** | ||
* Replace all classes with their mutated versions. | ||
*/ | ||
internal fun replaceClasses() = | ||
proxyPool.removeIf { proxy -> | ||
// If the proxy is unused, return false to keep it in the proxies list. | ||
if (!proxy.resolved) return@removeIf false | ||
internal fun replaceClasses() { | ||
synchronized(proxyPool) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does not seem necessary. The function is called after all patches have executed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For consistency it can be synchronized on iteration, just to have the same behavior everywhere. There is no performance overhead of doing this. |
||
proxyPool.removeIf { proxy -> | ||
// If the proxy is unused, return false to keep it in the proxies list. | ||
if (!proxy.resolved) return@removeIf false | ||
|
||
// If it has been used, replace the original class with the mutable class. | ||
remove(proxy.immutableClass) | ||
add(proxy.mutableClass) | ||
// If it has been used, replace the original class with the mutable class. | ||
remove(proxy.immutableClass) | ||
add(proxy.mutableClass) | ||
|
||
// Return true to remove the proxy from the proxies list. | ||
return@removeIf true | ||
// Return true to remove the proxy from the proxies list. | ||
return@removeIf true | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is synchronization needed here? Patches can also access the classes list, should they also synchronize? Would it not be possible to use a ConcurrentList so that we don't have to synchronize everytime the classes list is accessed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Iteration is not thread safe if another piece of code can change the list.
If there is no way the list can ever be changed after it is created then synchronization is not needed here.