Issue
I’m currently running into an issue where it is taking up to 20 seconds (!) for scroll/tap gestures (for the Appium server to respond w/ the gesture completed).
The goal is to get scrolls / taps down to ~<1s or even faster (I using my keyboard to send events & the idea is to have near-0 latency on the device executing what I’m typing/directing via keyboard).
Setup specs:
- Appium Client: Python client (Appium-Python-Client v3.1.1)
- Machine (my laptop): MacBook Air (M1, 2020) (Sonoma 14.0)
- Phone: iPhone 13 Pro Max (iOS version 17.1)
(phone connected directly to laptop via USB — all local setup)
Scroll Code
The following is my scrolling code — I originally had it running all synchronously but took the gesture off the main thread to ensure it was not any of my other application code blocking the next gesture. Both versions (synchronous & executing on a seperate thread) produce the same latency.
def _scroll(self, direction: str, duration_ms: int = 100, offset: int = 100):
start_x = self.device_center_x
end_x = self.device_center_x
# calculate start/end y positions
if direction == "up":
start_y = self.device_center_y - offset
end_y = self.device_center_y + offset
elif direction == "down":
start_y = self.device_center_y + offset
end_y = self.device_center_y - offset
else:
raise Exception(f"fatal: invalid scroll direction {direction}")
# perform the scroll
def execute_gesture(driver, start_x, start_y, end_x, end_y, duration_ms):
logger.debug(f"scroll [{'↑' if direction == 'up' else '↓'}] start")
actions = TouchAction(driver)
actions.press(x=start_x, y=start_y).move_to(x=end_x, y=end_y).wait(
ms=duration_ms
).release().perform()
logger.debug(f"scroll [{'↑' if direction == 'up' else '↓'}] end")
# run the gesture in a separate thread so we can continue to receive keyboard events
gesture_thread = threading.Thread(
target=execute_gesture,
args=(self.driver, start_x, start_y, end_x, end_y, duration_ms),
)
gesture_thread.start()
Tap Code
The following is my tap code.
def _tap(self, x: int, y: int):
def execute_gesture(driver, x, y):
logger.debug(f"tap start")
actions = TouchAction(driver)
actions.tap(x=x, y=y).perform()
logger.debug(f"tap end")
# run the gesture in a separate thread so we can continue to receive keyboard events
gesture_thread = threading.Thread(
target=execute_gesture, args=(self.driver, x, y)
)
gesture_thread.start()
Error Showing Latency
I’ve pinned down that the issue is in the test driver responding very slowly (and subsequently not serving later requests from my code). The below error shows the latency I’m experiencing executing a scroll:
[HTTP] --> POST /session/4cbf5668-97b4-48de-8e4a-f03bc392d79a/touch/perform
[HTTP] {"actions":[{"action":"press","options":{"x":214,"y":263}},{"action":"moveTo","options":{"x":214,"y":663}},{"action":"wait","options":{"ms":100}},{"action":"release","options":{}}]}
[XCUITestDriver@f45f (4cbf5668)] Calling AppiumDriver.performTouch() with args: [[{"action":"press","options":{"x":214,"y":263}},{"action":"moveTo","options":{"x":214,"y":663}},{"action":"wait","options":{"ms":100}},{"action":"release","options":{}}],"4cbf5668-97b4-48de-8e4a-f03bc392d79a"]
[XCUITestDriver@f45f (4cbf5668)] Executing command 'performTouch'
[XCUITestDriver@f45f (4cbf5668)] Got response with status 200: {"value":null,"sessionId":"3AA5E225-CFFE-48BE-B993-578AF65379AF"}
[XCUITestDriver@f45f (4cbf5668)] Received the following touch action: press(options={"x":214,"y":263})-moveTo(options={"x":214,"y":663})-wait(options={"ms":100})-release(options={})
[XCUITestDriver@f45f (4cbf5668)] Proxying [POST /wda/touch/perform] to [POST http://127.0.0.1:8100/session/3AA5E225-CFFE-48BE-B993-578AF65379AF/wda/touch/perform] with body: {"actions":[{"action":"press","options":{"x":214,"y":263}},{"action":"moveTo","options":{"x":214,"y":663}},{"action":"wait","options":{"ms":100}},{"action":"release","options":{}}]}
[XCUITestDriver@f45f (4cbf5668)] Responding to client with driver.performTouch() result: null
[HTTP] <-- POST /session/4cbf5668-97b4-48de-8e4a-f03bc392d79a/touch/perform 200 23623 ms - 14
[HTTP]
As you can see it took ~24s for the server to respond successfully.
The actual scroll completes nearly immediately, <~1s (then there is a long wait for the server to unblock).
Webdriver Config (capabilities)
{
"platformName": "iOS",
"automationName": "XCUITest",
"platformVersion": "17.1",
"udid": _omitted_,
"xcodeOrgId": _omitted_,
"xcodeSigningId": "iPhone Developer",
"noReset": False,
"newCommandTimeout": 60 * 60,
"waitForQuiescence": False, # tried this
"waitForIdleTimeout": 0, # tried this
}
Things I’ve Tried
- Restarting my iPhone
- Restarting my laptop
- Restarting the Appium server
- Deleting the
WebDriverAgentRunner-Runner
app (on my phone), restarting the Appium server, then running my application again (which installs it)
If I can’t solve this would also love to know other recommendations to achieve the low latency I’m trying to go for (though I’m enjoying using Appium!).
Thanks for all the help!