From f2411848f7d6a19d18926017455b4c717b375443 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi Date: Fri, 1 Mar 2024 12:22:03 +0900 Subject: [PATCH] Revert "Make `asyncio.sleep(0)` run faster (#4568)" (#4583) --- docs/project/changelog.md | 3 --- pyproject.toml | 1 - src/js/api.ts | 5 ----- src/js/package.json | 2 +- src/js/scheduler.ts | 19 ------------------- src/js/test/unit/scheduler.test.ts | 21 --------------------- src/js/types.ts | 1 - src/py/pyodide/webloop.py | 7 ++----- src/tests/test_webloop.py | 17 ----------------- 9 files changed, 3 insertions(+), 73 deletions(-) delete mode 100644 src/js/scheduler.ts delete mode 100644 src/js/test/unit/scheduler.test.ts diff --git a/docs/project/changelog.md b/docs/project/changelog.md index 83d2b40d1..6c8c8f894 100644 --- a/docs/project/changelog.md +++ b/docs/project/changelog.md @@ -54,9 +54,6 @@ myst: - {{ Enhancement }} Fixed a memory leak when iterating over a PyProxy. {pr}`4546` -- {{ Enhancement }} `asyncio.sleep(0)` now runs the next task a lot faster. - {pr}`4568` - - {{ Fix }} `pyodide.mountNativeFS` will no longer silently overwrite an existing nonempty directory. Also it throws much clearer error messages when it fails. diff --git a/pyproject.toml b/pyproject.toml index 8cbaace80..6bdfd4da4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,6 @@ module = [ "matplotlib.*", "PIL.*", "pyodide_js", - "pyodide_js._api", "pytest_pyodide", "pytest_pyodide.runner", "pytest_pyodide.utils", diff --git a/src/js/api.ts b/src/js/api.ts index 9e2b79a54..fc3fc301b 100644 --- a/src/js/api.ts +++ b/src/js/api.ts @@ -8,7 +8,6 @@ import { type PyProxy, type PyDict } from "generated/pyproxy"; import { loadBinaryFile, nodeFSMod } from "./compat"; import { version } from "./version"; import { setStdin, setStdout, setStderr } from "./streams"; -import { scheduleCallback } from "./scheduler"; import { TypedArray } from "./types"; import { IN_NODE } from "./environments"; @@ -52,10 +51,6 @@ API.saveState = () => API.pyodide_py._state.save_state(); /** @private */ API.restoreState = (state: any) => API.pyodide_py._state.restore_state(state); -// Used in webloop -/** @private */ -API.scheduleCallback = scheduleCallback; - function ensureMountPathExists(path: string): void { Module.FS.mkdirTree(path); const { node } = Module.FS.lookupPath(path, { diff --git a/src/js/package.json b/src/js/package.json index 0672b96f4..aa1902ea2 100644 --- a/src/js/package.json +++ b/src/js/package.json @@ -81,7 +81,7 @@ "scripts": { "build": "tsc --noEmit && node esbuild.config.mjs", "test": "npm-run-all test:*", - "test:unit": "cross-env TEST_NODE=1 ts-mocha --exit --node-option=experimental-loader=./test/loader.mjs --node-option=experimental-wasm-stack-switching -p tsconfig.test.json test/unit/**/*.test.*", + "test:unit": "cross-env TEST_NODE=1 ts-mocha --node-option=experimental-loader=./test/loader.mjs --node-option=experimental-wasm-stack-switching -p tsconfig.test.json test/unit/**/*.test.*", "test:node": "cross-env TEST_NODE=1 mocha test/integration/**/*.test.js", "test:browser": "mocha test/integration/**/*.test.js", "tsc": "tsc --noEmit", diff --git a/src/js/scheduler.ts b/src/js/scheduler.ts deleted file mode 100644 index 3876812ed..000000000 --- a/src/js/scheduler.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Schedule a callback. Supports both immediate and delayed callbacks. - * @param callback The callback to be scheduled - * @param timeout The delay in milliseconds before the callback is called - */ -export function scheduleCallback(callback: () => void, timeout: number = 0) { - // In modern browsers, setTimeout has throttling minimum delay (mostly 4ms). - // So to support immediate callbacks, we use MessageChannel if the delay is less than 4ms. - // Ref0: https://github.com/pyodide/pyodide/issues/4006 - // Ref1: (firefox) https://developer.mozilla.org/en-US/docs/Web/API/setTimeout - // Ref2: (chrome) https://developer.chrome.com/blog/timer-throttling-in-chrome-88 - if (timeout < 4) { - const channel = new MessageChannel(); - channel.port1.onmessage = () => callback(); - channel.port2.postMessage(""); - } else { - setTimeout(callback, timeout); - } -} diff --git a/src/js/test/unit/scheduler.test.ts b/src/js/test/unit/scheduler.test.ts deleted file mode 100644 index 324efd3c2..000000000 --- a/src/js/test/unit/scheduler.test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as chai from "chai"; -import { scheduleCallback } from "../../scheduler"; - -describe("scheduleCallback", () => { - // Note: This test requires `--exit` flag to be set for mocha - // to avoid hanging the process - // see: https://github.com/facebook/react/issues/26608 - it("should call the callback immediately if timeout is 0", () => { - const start = Date.now(); - scheduleCallback(() => { - chai.assert.isAtMost(Date.now() - start, 4); - }); - }); - - it("should call the callback after the given timeout", () => { - const start = Date.now(); - scheduleCallback(() => { - chai.assert.isAtLeast(Date.now() - start, 10); - }, 10); - }); -}); diff --git a/src/js/types.ts b/src/js/types.ts index d8c3f7f24..1479502f9 100644 --- a/src/js/types.ts +++ b/src/js/types.ts @@ -322,7 +322,6 @@ export interface API { runPythonInternal_dict: any; saveState: () => any; restoreState: (state: any) => void; - scheduleCallback: (callback: () => void, timeout: number) => void; package_loader: any; importlib: any; diff --git a/src/py/pyodide/webloop.py b/src/py/pyodide/webloop.py index 12a104e11..3aa776aa8 100644 --- a/src/py/pyodide/webloop.py +++ b/src/py/pyodide/webloop.py @@ -11,7 +11,7 @@ from typing import Any, TypeVar, overload from .ffi import IN_BROWSER, create_once_callable if IN_BROWSER: - from pyodide_js._api import scheduleCallback + from js import setTimeout T = TypeVar("T") S = TypeVar("S") @@ -343,10 +343,7 @@ class WebLoop(asyncio.AbstractEventLoop): else: raise - scheduleCallback( - create_once_callable(run_handle, _may_syncify=True), delay * 1000 - ) - + setTimeout(create_once_callable(run_handle, _may_syncify=True), delay * 1000) return h def _decrement_in_progress(self, *args): diff --git a/src/tests/test_webloop.py b/src/tests/test_webloop.py index 4219bce04..fa3e663fd 100644 --- a/src/tests/test_webloop.py +++ b/src/tests/test_webloop.py @@ -497,20 +497,3 @@ async def test_inprogress(selenium): loop._no_in_progress_handler = None loop._keyboard_interrupt_handler = None loop._system_exit_handler = None - - -@run_in_pyodide -async def test_zero_timeout(selenium): - import asyncio - import time - - now = time.time() - - for _ in range(1000): - await asyncio.sleep(0) - - done = time.time() - elapsed = done - now - - # Very rough check, we hope it's less than 4s (1000 * 4ms [setTimeout delay in most browsers]) - assert elapsed < 4, f"elapsed: {elapsed}s"