定时器调用性能优化
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user