定时器调用性能优化

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

View File

@@ -4,6 +4,9 @@ import android.os.Handler
import android.os.Looper
import android.os.SystemClock
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 kotlin.random.Random
@@ -14,6 +17,7 @@ class Timer(
runtime: ScriptRuntime,
looper: Looper
) {
private val myLooper: Looper = looper
private val mHandlerCallbacks = ConcurrentHashMap<Int, Runnable?>()
private val mRuntime: ScriptRuntime = runtime
private val mHandler: Handler = Handler(looper)
@@ -21,10 +25,10 @@ class Timer(
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 r = Runnable {
callFunction(callback, null, args as Array<Any>)
callFunction(callback, null, args)
mHandlerCallbacks.remove(id)
}
mHandlerCallbacks[id] = r
@@ -32,9 +36,13 @@ class Timer(
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 {
mRuntime.bridges.callFunction(callback, thiz, args)
(callback as BaseFunction).call(Context.getCurrentContext(),callback.parentScope,
thiz as? Scriptable?, map.toTypedArray()
)
} catch (e: Exception) {
if (isUiLoop) {
mRuntime.exit(e)
@@ -52,12 +60,12 @@ class Timer(
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 r: Runnable = object : Runnable {
override fun run() {
if (mHandlerCallbacks[id] == null) return
callFunction(listener, null, args as Array<Any>)
callFunction(listener, null, args)
postDelayed(this, interval)
}
}
@@ -67,22 +75,26 @@ class Timer(
}
fun postDelayed(r: Runnable, interval: Long) {
val uptime = SystemClock.uptimeMillis() + interval
mHandler.postAtTime(r, uptime)
synchronized(myLooper) {
val uptime = SystemClock.uptimeMillis() + interval
mHandler.postAtTime(r, uptime)
}
}
fun post(r: Runnable) {
mHandler.post(r)
synchronized(myLooper) {
mHandler.post(r)
}
}
fun clearInterval(id: Int): Boolean = clearCallback(id)
fun clearImmediate(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 r = Runnable {
callFunction(listener, null, args as Array<Any>)
callFunction(listener, null, args)
mHandlerCallbacks.remove(id)
}
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.runtime.ScriptRuntime
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.ThreadFactory
import java.util.concurrent.atomic.AtomicLong
@@ -23,7 +25,14 @@ class Threads(private val mRuntime: ScriptRuntime) {
private var mExit = false
private val looperTask = Loopers.AsyncTask("AsyncTaskThreadPool")
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
})
@@ -33,17 +42,20 @@ class Threads(private val mRuntime: ScriptRuntime) {
return if (thread === mainThread) mMainThreadProxy else thread
}
fun runTaskForThreadPool(runnable: Runnable) {
fun runTaskForThreadPool(runnable: BaseFunction) {
if (mTaskCount.addAndGet(1) == 1L) mRuntime.loopers.addAsyncTask(looperTask)
threadPool.execute {
try {
runnable.run()
runnable.call(
Context.getCurrentContext(), runnable.parentScope, runnable,
emptyArray()
)
} catch (e: Throwable) {
if (!ScriptInterruptedException.causedByInterrupted(e)) {
mRuntime.console.error("$this: ", e)
}
} finally {
if (mTaskCount.addAndGet(-1) == 0L){
if (mTaskCount.addAndGet(-1) == 0L) {
mRuntime.loopers.removeAsyncTask(looperTask)
}
}

View File

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