定时器调用性能优化

This commit is contained in:
aiselp
2023-06-10 19:44:50 +08:00
parent f93aa9acfc
commit b0d32710a1
4 changed files with 62 additions and 31 deletions

View File

@@ -54,10 +54,11 @@ class Loopers(val runtime: ScriptRuntime) {
private var mMainLooperQuitHandler: LooperQuitHandler? = null private var mMainLooperQuitHandler: LooperQuitHandler? = null
private val allTasks = ConcurrentLinkedQueue<AsyncTask>() private val allTasks = ConcurrentLinkedQueue<AsyncTask>()
val mTimer: Timer val mTimer: Timer
val myLooper: Looper
init { init {
prepare() prepare()
val myLooper = Looper.myLooper()!! myLooper = Looper.myLooper()!!
mTimer = Timer(runtime, myLooper) mTimer = Timer(runtime, myLooper)
waitWhenIdle = myLooper == Looper.getMainLooper() waitWhenIdle = myLooper == Looper.getMainLooper()
} }
@@ -69,12 +70,16 @@ class Loopers(val runtime: ScriptRuntime) {
} }
fun addAsyncTask(task: AsyncTask) { fun addAsyncTask(task: AsyncTask) {
allTasks.add(task) synchronized(myLooper) {
allTasks.add(task)
}
} }
fun removeAsyncTask(task: AsyncTask) { fun removeAsyncTask(task: AsyncTask) {
allTasks.remove(task) synchronized(myLooper) {
mTimer.post(EMPTY_RUNNABLE) allTasks.remove(task)
mTimer.post(EMPTY_RUNNABLE)
}
} }
private fun checkTask(): Boolean { private fun checkTask(): Boolean {
@@ -86,15 +91,17 @@ class Loopers(val runtime: ScriptRuntime) {
} }
private fun shouldQuitLooper(): Boolean { private fun shouldQuitLooper(): Boolean {
if (Thread.currentThread().isInterrupted) return true synchronized(myLooper) {
if (mTimer.hasPendingCallbacks()) return false if (Thread.currentThread().isInterrupted) return true
//检查是否有运行中的线程 if (mTimer.hasPendingCallbacks()) return false
if (checkTask()) return false //检查是否有运行中的线程
if (waitWhenIdle) return false if (checkTask()) return false
if ((Context.getCurrentContext() as AutoJsContext).hasPendingContinuation()) { if (waitWhenIdle) return false
return false if ((Context.getCurrentContext() as AutoJsContext).hasPendingContinuation()) {
return false
}
return true
} }
return true
} }
private fun initServantThread() { private fun initServantThread() {
@@ -111,7 +118,7 @@ class Loopers(val runtime: ScriptRuntime) {
get() { get() {
if (mServantLooper == null) { if (mServantLooper == null) {
initServantThread() initServantThread()
val lock = this as Object val lock = this as java.lang.Object
synchronized(lock) { synchronized(lock) {
try { try {
lock.wait() lock.wait()

View File

@@ -4,6 +4,9 @@ import android.os.Handler
import android.os.Looper import android.os.Looper
import android.os.SystemClock import android.os.SystemClock
import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.ScriptRuntime
import org.mozilla.javascript.BaseFunction
import org.mozilla.javascript.Context
import org.mozilla.javascript.Scriptable
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import kotlin.random.Random import kotlin.random.Random
@@ -14,6 +17,7 @@ class Timer(
runtime: ScriptRuntime, runtime: ScriptRuntime,
looper: Looper looper: Looper
) { ) {
private val myLooper: Looper = looper
private val mHandlerCallbacks = ConcurrentHashMap<Int, Runnable?>() private val mHandlerCallbacks = ConcurrentHashMap<Int, Runnable?>()
private val mRuntime: ScriptRuntime = runtime private val mRuntime: ScriptRuntime = runtime
private val mHandler: Handler = Handler(looper) private val mHandler: Handler = Handler(looper)
@@ -21,10 +25,10 @@ class Timer(
constructor(runtime: ScriptRuntime, ) : this(runtime, Looper.myLooper()!!) constructor(runtime: ScriptRuntime, ) : this(runtime, Looper.myLooper()!!)
fun setTimeout(callback: Any, delay: Long, vararg args: Any): Int { fun setTimeout(callback: Any, delay: Long, vararg args: Any?): Int {
val id = createTimerId() val id = createTimerId()
val r = Runnable { val r = Runnable {
callFunction(callback, null, args as Array<Any>) callFunction(callback, null, args)
mHandlerCallbacks.remove(id) mHandlerCallbacks.remove(id)
} }
mHandlerCallbacks[id] = r mHandlerCallbacks[id] = r
@@ -32,9 +36,13 @@ class Timer(
return id return id
} }
private fun callFunction(callback: Any, thiz: Any?, args: Array<Any>) { private fun callFunction(callback: Any, thiz: Any?, args :Any?) {
val myArgs = args?.let { args as Array<*> }?: emptyArray<Any>()
val map = myArgs.map { Context.javaToJS(it, callback as BaseFunction) }
try { try {
mRuntime.bridges.callFunction(callback, thiz, args) (callback as BaseFunction).call(Context.getCurrentContext(),callback.parentScope,
thiz as? Scriptable?, map.toTypedArray()
)
} catch (e: Exception) { } catch (e: Exception) {
if (isUiLoop) { if (isUiLoop) {
mRuntime.exit(e) mRuntime.exit(e)
@@ -52,12 +60,12 @@ class Timer(
return id return id
} }
fun setInterval(listener: Any, interval: Long, vararg args: Any): Int { fun setInterval(listener: Any, interval: Long, vararg args: Any?): Int {
val id = createTimerId() val id = createTimerId()
val r: Runnable = object : Runnable { val r: Runnable = object : Runnable {
override fun run() { override fun run() {
if (mHandlerCallbacks[id] == null) return if (mHandlerCallbacks[id] == null) return
callFunction(listener, null, args as Array<Any>) callFunction(listener, null, args)
postDelayed(this, interval) postDelayed(this, interval)
} }
} }
@@ -67,22 +75,26 @@ class Timer(
} }
fun postDelayed(r: Runnable, interval: Long) { fun postDelayed(r: Runnable, interval: Long) {
val uptime = SystemClock.uptimeMillis() + interval synchronized(myLooper) {
mHandler.postAtTime(r, uptime) val uptime = SystemClock.uptimeMillis() + interval
mHandler.postAtTime(r, uptime)
}
} }
fun post(r: Runnable) { fun post(r: Runnable) {
mHandler.post(r) synchronized(myLooper) {
mHandler.post(r)
}
} }
fun clearInterval(id: Int): Boolean = clearCallback(id) fun clearInterval(id: Int): Boolean = clearCallback(id)
fun clearImmediate(id: Int): Boolean = clearCallback(id) fun clearImmediate(id: Int): Boolean = clearCallback(id)
fun clearTimeout(id: Int): Boolean = clearCallback(id) fun clearTimeout(id: Int): Boolean = clearCallback(id)
fun setImmediate(listener: Any, vararg args: Any): Int { fun setImmediate(listener: Any, vararg args: Any?): Int {
val id = createTimerId() val id = createTimerId()
val r = Runnable { val r = Runnable {
callFunction(listener, null, args as Array<Any>) callFunction(listener, null, args)
mHandlerCallbacks.remove(id) mHandlerCallbacks.remove(id)
} }
mHandlerCallbacks[id] = r mHandlerCallbacks[id] = r

View File

@@ -6,6 +6,8 @@ import org.autojs.autojs.core.looper.MainThreadProxy
import org.autojs.autojs.core.looper.TimerThread import org.autojs.autojs.core.looper.TimerThread
import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.exception.ScriptInterruptedException import org.autojs.autojs.runtime.exception.ScriptInterruptedException
import org.mozilla.javascript.BaseFunction
import org.mozilla.javascript.Context
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.ThreadFactory import java.util.concurrent.ThreadFactory
import java.util.concurrent.atomic.AtomicLong import java.util.concurrent.atomic.AtomicLong
@@ -23,7 +25,14 @@ class Threads(private val mRuntime: ScriptRuntime) {
private var mExit = false private var mExit = false
private val looperTask = Loopers.AsyncTask("AsyncTaskThreadPool") private val looperTask = Loopers.AsyncTask("AsyncTaskThreadPool")
private val threadPool = Executors.newFixedThreadPool(20, ThreadFactory { private val threadPool = Executors.newFixedThreadPool(20, ThreadFactory {
val thread = Thread(it) val thread = Thread(fun() {
Context.enter()
try {
it.run()
} finally {
Context.exit()
}
})
thread.name = mainThread.name + " (AsyncThread)" thread.name = mainThread.name + " (AsyncThread)"
thread thread
}) })
@@ -33,17 +42,20 @@ class Threads(private val mRuntime: ScriptRuntime) {
return if (thread === mainThread) mMainThreadProxy else thread return if (thread === mainThread) mMainThreadProxy else thread
} }
fun runTaskForThreadPool(runnable: Runnable) { fun runTaskForThreadPool(runnable: BaseFunction) {
if (mTaskCount.addAndGet(1) == 1L) mRuntime.loopers.addAsyncTask(looperTask) if (mTaskCount.addAndGet(1) == 1L) mRuntime.loopers.addAsyncTask(looperTask)
threadPool.execute { threadPool.execute {
try { try {
runnable.run() runnable.call(
Context.getCurrentContext(), runnable.parentScope, runnable,
emptyArray()
)
} catch (e: Throwable) { } catch (e: Throwable) {
if (!ScriptInterruptedException.causedByInterrupted(e)) { if (!ScriptInterruptedException.causedByInterrupted(e)) {
mRuntime.console.error("$this: ", e) mRuntime.console.error("$this: ", e)
} }
} finally { } finally {
if (mTaskCount.addAndGet(-1) == 0L){ if (mTaskCount.addAndGet(-1) == 0L) {
mRuntime.loopers.removeAsyncTask(looperTask) mRuntime.loopers.removeAsyncTask(looperTask)
} }
} }

View File

@@ -1,8 +1,8 @@
#Sat Jun 10 13:06:56 CST 2023 #Sat Jun 10 19:42:58 CST 2023
BUILD_TIME=1686373616005 BUILD_TIME=1686397378556
COMPILE_SDK_VERSION=33 COMPILE_SDK_VERSION=33
JAVA_VERSION=20 JAVA_VERSION=20
MIN_SDK_VERSION=24 MIN_SDK_VERSION=24
TARGET_SDK_VERSION=33 TARGET_SDK_VERSION=33
VERSION_BUILD=1910 VERSION_BUILD=1911
VERSION_NAME=6.3.1 VERSION_NAME=6.3.1