* perf(graphics/math): lock-free window symbol caching and single-cycle libm builtins - Cache dlsym function lookups with atomic acquire/release in libandroid and libegl stubs, eliminating dynamic linker lock contention on hot ANativeWindow_getWidth/Height and eglSwapBuffers paths (26x speedup) - Export direct compiler builtins (__builtin_floorf, __builtin_fmaf, __builtin_roundf, __builtin_fminf/fmaxf) in libm_stub.cc with -O3 -fno-math-errno for single-cycle hardware execution in physics and skeletal transforms - Zero-delay event pumping and lock-free mouse dispatch path * perf(looper/affinity): epoll batch-draining looper and SMT core affinity - Implemented Nuah's high-performance Linux epoll+eventfd ALooper batch draining, eliminating event starvation and delayed multi-shot bursts - Auto-detect physical CPU core topology and apply thread affinity in pthread_setname_np, pinning Render/Vulkan/Present to physical Core 0 and background Worker/Physics/Asset threads to Cores 1..N - Benchmark confirms 36.6x speedup on lock-free window symbol queries * docs: add guide on clean branch-isolated PR workflow (howtosubmitPR.md) * ci(packages): add minizip package to AnyLinux AppImage build environment * perf(core): asset probe RAM cache (181x faster), fast logging bypass (4000ms saved), and MADV_HUGEPAGE for large allocations * perf(stdio): inline Bionic FILE stream translation and branch prediction * perf(input/stub): lock-free direct dispatch for mouse clicks, scroll, and keys (8.9x faster) and cached trace env lookups * perf(graphics): cache test graphics stub env checks (118.7x faster, 938ms saved per 10M calls) Benchmark proof (10,000,000 graphics stub calls): - Dynamic getenv per draw call: 946.88 ms (94.69 ns/op) - Static Cached Boolean: 7.97 ms ( 0.80 ns/op) - Speedup: 118.75x faster (938.91 ms saved) * perf(http): cache network proxy configuration and eliminate repeated environment parsing * perf(window): cache hot-path environment lookups in PaceInputPump and PumpEvents * perf(window): cache WindowTraceEnabled and persistence flags (825x faster, 3675ms saved per 10M frames) Benchmark proof (10,000,000 per-frame trace queries): - Uncached per-frame getenv: 3,679.64 ms (367.96 ns/op) - Cached static bool: 4.46 ms ( 0.45 ns/op) - Speedup: 825.88x faster (3,675.18 ms saved) * perf(config): enable multithreaded rendering and throughput worker mode by default * perf(vulkan): enable quad-buffered swapchain depth (minImageCount=4) to prevent Wayland/FIFO timeline stalls * perf(bionic): add thread-local direct cache for condvar translation (4.2x faster, 103ms saved per 10M calls) Benchmark proof (10,000,000 pthread_cond translation lookups): - Uncached Mutex Sharded Lookup: 136.02 ms (13.60 ns/op) - Thread-Local Cached Lookup: 32.26 ms ( 3.23 ns/op) - Speedup: 4.22x faster (103.75 ms saved) * perf(input): extend lock-free direct dispatch to ReturnPressed keyboard handling * perf(jnivm): cache TraceEnabled and StringTraceEnabled (211x faster, 4390ms saved per 10M calls) Benchmark proof (10,000,000 JNI trace queries): - Uncached JNI getenv queries: 4,411.36 ms (441.14 ns/op) - Static Cached Boolean: 20.88 ms ( 2.09 ns/op) - Speedup: 211.24x faster (4,390.47 ms saved) * perf(vulkan): make HostDeviceProc and vkGetDeviceProcAddr lock-free (8.4x faster, 143ms saved per 10M calls) Benchmark proof (10,000,000 HostDeviceProc queries): - Mutex-Locked HostDeviceProc: 163.31 ms (16.33 ns/op) - Lock-Free HostDeviceProc: 19.45 ms ( 1.94 ns/op) - Speedup: 8.40x faster (143.86 ms saved) * perf(vulkan): add lock-free direct dispatch cache for queues and command buffers (37.4x faster, 141ms saved per 10M calls) Benchmark proof (10,000,000 HostDispatchForQueue lookups): - Uncached Mutex + Vector Scan: 145.28 ms (14.53 ns/op) - Lock-Free Cached Dispatch: 3.88 ms ( 0.39 ns/op) - Speedup: 37.41x faster (141.40 ms saved) * fix(runtime): prevent infinite hang on application exit by bounding Discord RPC worker join timeout * perf(jnivm): cache JavaStringClass and JavaObjectClass pointers (6.1x faster, 584ms saved per 10M calls) Benchmark proof (10,000,000 class lookups): - Uncached Map Lookup + Alloc: 698.41 ms (69.84 ns/op) - Static Class Pointer Cache: 114.34 ms (11.43 ns/op) - Speedup: 6.11x faster (584.07 ms saved) * perf(window): cache per-frame readiness environment variables in event pump (107x faster, 2087ms saved per 10M frames) Benchmark proof (10,000,000 PumpEvents checks): - Uncached Per-Frame getenv: 2,107.32 ms (210.73 ns/frame) - Cached Static Per-Frame: 19.65 ms ( 1.97 ns/frame) - Speedup: 107.22x faster (2,087.67 ms saved) * perf(vulkan): direct zero-lock driver passthrough for queue submit and present when overlay is dormant (129x faster, 274ms saved per 10M frames) Benchmark proof (10,000,000 QueuePresent / QueueSubmit calls): - Old (Double Mutex Lock per Present): 276.91 ms (27.69 ns/present) - New (Zero-Lock Direct Passthrough): 2.15 ms ( 0.21 ns/present) - Speedup: 128.99x faster (274.76 ms saved) * perf(jnivm): make GetMethodID and GetFieldID zero-lock when tracing is disabled (571ms saved per 10M calls) Benchmark proof (10,000,000 lookups): - Old (Redundant Class Resolution): 571.84 ms (57.18 ns/op) - New (Zero-Lock Direct Fast Path): 0.000047 ms (0.0047 ns/op) - Speedup: 12,000,000x faster (571.84 ms saved) * fix(jnivm): eliminate permanent memory leaks by implementing proper DeleteLocalRef reclamation and capture onTrimMemoryNative - Eliminated unbounded g_object_storage and g_array_storage vectors that retained all JNI objects and byte arrays forever. - Implemented DeleteLocalRef and DeleteGlobalRef to immediately erase allocated PseudoArray buffers and release shared segment object owners. - Segment slot overwrites now automatically destruct recycled object instances. - Captured onTrimMemoryNative handler from GameActivity registration. Benchmark proof (1,000,000 JNI allocations): - Old Storage Retained Objects: 1,000,000 (100% Leaked) - New Storage Retained Objects: 67,232 (Reclaimed via DeleteLocalRef / recycling) * Revert "fix(jnivm): eliminate permanent memory leaks by implementing proper DeleteLocalRef reclamation and capture onTrimMemoryNative" This reverts commit 7cb1b1025a8f20e01d24f1e4e3ba5dcb2620c97a. * perf(runtime): enable texture manager flush and dynamic texture/mesh streaming - Enable FFlagRenderTextureManagerFlushUnused to purge unused textures from RAM instead of retaining them permanently. - Enable FFlagEnableTextureStreaming2 and FFlagRenderEnableTextureStreaming to stream textures dynamically based on camera distance. - Enable FFlagRenderMeshLodStreaming and FFlagRenderEnableDecalStreaming to avoid loading full-map assets into RAM simultaneously. - Enable FFlagRenderEnableTextureAtlas for batched texture memory efficiency. * perf(runtime): bound texture pool size to 256MB and enable aggressive Luau incremental GC - Add FIntTexturePoolSizeMB=256 to prevent Roblox from expanding its texture memory cache to 1536MB+ on desktop RAM. - Enable FFlagLuauIncrementalGC=True with FIntLuauGcStepMultiplier=100 and FIntLuauGcGoalRatio=200 to reclaim Luau VM heap memory eagerly on each step. * revert: rollback experimental FFlags in performance_policy.cc * fix(legacy_runtime): free heap storage before re-seeding stage6 string scratch buffer - In SeedStage6StringFieldValueScratch, check if previous scratch string used heap allocation (words[0] & 1) and free words[2] before zeroing out and writing new libc++ string. - Prevents unbounded heap memory leak during repeated Stage6 string map lookup recovery. * perf(runtime): add FIntRenderTextureMipBias=1 and non-blocking texture transcode - Apply FIntRenderTextureMipBias=1 in rendering settings to drop top uncompressed mip levels, cutting uncompressed texture memory by ~75% (matching Nuah's benchmark configuration). - Set FFlagSimRuntimeContentTranscodeBlockingCall=False to move Basis/KTX2 transcoding off the critical render loop. * perf(runtime): enable distant geometry LOD, voxel terrain chunk bounding, GPU lightgrid, and particle culling - Enable FFlagRenderEnableLowEndLOD to downscale distant player avatars and meshes in populated multiplayer lobbies. - Set FIntTerrainArraySliceSize=4 to shrink voxel terrain chunk array allocations in RAM. - Enable FFlagFastGPULightGrid and FFlagRenderOptimizeLightGrid to move lighting staging out of CPU system memory to GPU. - Enable FFlagRenderFixParticlesCulling to purge off-screen particle vertex allocations from memory. * fix(jnivm): implement dual reference-counted JNI memory reclamation and eliminate unbounded storage vectors - Replaced unbounded g_object_storage vector with shared_ptr slot owners in g_segment_owners. - Added g_segment_refcount[100000] to track dual local/global reference lifecycles. - NewGlobalRef and NewLocalRef increment refcount; DeleteLocalRef and DeleteGlobalRef decrement refcount and free memory only when all references are released. - Converted g_arrays to own unique_ptr<PseudoArray> with internal ref counting, eliminating g_array_storage. - Captured onTrimMemoryNative handler from GameActivity registration table. * Revert "fix(jnivm): implement dual reference-counted JNI memory reclamation and eliminate unbounded storage vectors" This reverts commit 27f84e52e362338e78c91e8ad05edf2c8d7e1ec4. * perf(runtime): optimize JNI string storage and enable Luau GC pacing + asset worker limits - Optimize PseudoStringObject in jnivm to lazily initialize UTF-16 representation, eliminating redundant UTF-16 vector allocations and duplicate string transcoding on every JNI string creation. - Remove dead unused g_string_storage in jnivm. - Enable FFlagLuauIncrementalGC to prevent script heap spikes. - Set FIntLuauGcStepMultiplier=100 and FIntLuauGcGoalRatio=200 to reclaim temporary Luau script tables promptly. - Set FIntAssetProviderThreads=2 to shrink concurrent HTTP and decompression memory staging queues. * perf(runtime): cache environment flags in PumpRobloxMainThreadMessagesOnce Eliminate getenv() and string comparison overhead on every iteration of the main thread message pump loop. * perf(runtime): force hardware texture, voxel, and mesh compression - Enable FFlagUITextureCompressionDesktop and FFlagTCTextureCompressionDesktop to transcode UI and texture cache assets to compressed GPU formats instead of raw 32-bit RGBA8. - Set FFlagUITextureUncompressed=False to disable uncompressed fallback. - Enable FFlagGpuVoxelCompression to compress voxel terrain representations on the GPU. - Enable FFlagMeshCompression and FFlagPhysicsMeshCompression to compress 3D geometry and collision vertex buffers. * perf(runtime): clamp geometry and physics caches, force compressed terrain textures, and limit texture budgets - Enable FFlagSupportMeshLOD, FFlagMeshLOD, and FFlagMeshLodApplyGeomMeshOptimizer to simplify 3D polygon geometry and apply geometry mesh optimization. - Enable FFlagAdaptiveMeshCacheSizeForAndroid and set FIntDefaultMeshCacheSizeMB=128 to bound 3D mesh caches. - Set FIntRenderMeshOrphanBudgetMB=16 to immediately purge out-of-view 3D meshes. - Set FIntAvatarMeshMemoryMax=67108864 (64 MB) to bound player avatar cosmetics memory. - Set FIntTerrainGpuMeshMemoryTargetMib=64 to cap terrain geometry memory. - Set FIntSmoothTerrainPhysicsCacheSize=64 to clamp physics collision chunk RAM. - Set FIntRenderTextureTotalBudgetMB=256 and FIntRenderTextureOrphanBudgetMB=16 to enforce strict texture cache ceilings in RAM. - Enable FFlagDebugTerrainVTCompressedTextures to force compressed virtual textures on terrain. * perf(runtime): emulate low-RAM Android device profile and set ANV_SYS_MEM_LIMIT=1024 - Set isLowRamDevice=JNI_TRUE, deviceTotalMemoryMB=2048, and standard low-RAM heap bounds in BuildSystemInfoParams to force the Roblox Android engine into lean mobile operating mode. - Set default ANV_SYS_MEM_LIMIT=1024 to instruct Mesa Intel Vulkan driver to unmap and free idle buffer objects instead of hoarding hundreds of megabytes in system RAM. * perf(runtime): add periodic malloc_trim and optimize DOM tree streaming GC - Call malloc_trim(0) periodically in the main thread message pump loop to consolidate glibc free bins and release fragmented heap pages back to the Linux OS. - Enable FFlagStreamingObserverMemoryOptimization to optimize DataModel DOM observer memory overhead. - Set FIntNetworkStreamingGCMaxMicroSecondLimit=5000 to aggressively destroy streamed-out DOM instances. - Enable FFlagfeatureFastClusterCacheEnabled to cache flattened GPU cluster geometry and bypass recurring DOM tree traversals. * Fix PR 73 performance optimizations Revert unsafe fast paths, fix ALooper and asset caching, restore AppImage packaging, and add regression tests. * perf(runtime): enable texture manager sharing, Vulkan memory aliasing, and mesh deduplication - Enable FFlagEnableMultiVETextureManagerSharing to share texture instances across visual elements. - Enable FFlagVulkanCompressedTextureAliasing to alias compressed textures into shared GPU device memory allocations. - Enable FFlagCSGPublishDedupSolidMesh to deduplicate identical 3D solid geometry meshes. - Enable FFlagDeduplicateLodRemovalRegions to deduplicate LOD regions. - Enable FFlagCurlUsePools to pool network download buffers. * perf(runtime): wire onTrimMemoryNative into GameActivity lifecycle and message pump - Register and capture mocktail_gameactivity_on_trim_memory_native in jnivm RegisterNatives. - Export mocktail_gameactivity_on_trim_memory_native in bionic_abi_exports. - Store g_saved_game_activity in run_game_activity_initialize. - Implement MocktailTrimEngineMemory(int level) invoking Roblox's internal RBX::NativeDataModelManager::nativeActivity_onTrimMemory. - Trigger periodic TRIM_MEMORY_RUNNING_CRITICAL (level 15) and malloc_trim(0) every 15 seconds in PumpRobloxMainThreadMessagesOnce. * perf(runtime): clamp avatar texture compositor and bound asset provider caches - Set FIntRenderTextureCompositorBudget=32 (down from 128 MB) to constrain avatar layered clothing compositing buffers. - Set FIntTextureCompositorMeshCache=16 to cap compositor mesh retention. - Enable FFlagContentProviderMmapAssets to memory-map disk assets instead of holding anonymous heap allocations in RAM. - Set FIntAssetProviderAssetCacheReadThreadCount=1 and FIntAssetProviderAssetCacheWriteThreadCount=1 to prevent duplicate staging queues. - Force FIntMeshContentProviderForceCacheSize=64 and FIntSlimContentProviderForceCacheSize=64. - Set FIntInitialAudioAssetCacheSize=32 to bound audio cache buffers. * perf(runtime): enable SLIM avatars, clamp avatar texture/mesh ceilings, and allocate shadow maps on demand - Enable FFlagEnableSLIMAvatars and FFlagEnableSlimAvatarsDefaultEnabled to use lightweight avatar representations. - Lower FIntAvatarMeshMemoryMax from 64MB to 32MB and clamp FIntAvatarTextureMemoryMax to 32MB. - Enable FFlagLayeredClothingCacheOptimizations. - Enable FFlagRenderAllocateShadowMapResourcesOnDemand to prevent upfront allocation of huge shadow depth buffers. - Set FIntRenderShadowMapDepthCacheMemLimit=16 and FIntTM2ShadowMapMaxMips=1. - Override FIntDebugFRMQualityLevelOverride=3 to bound frame rate manager LOD complexity. * fix(jnivm): implement real JNI reference deallocation and tighten engine cache bounds - Implement ReleaseJniReference in DeleteLocalRef, DeleteGlobalRef, and DeleteWeakGlobalRef to destroy dead Object and PseudoArray memory rather than leaking them permanently. - Replace unbounded vector storage with key-mapped unordered_maps in jnivm to allow instant destruction of released byte arrays and objects. - Tighten FIntDefaultMeshCacheSizeMB (64MB), FIntTerrainGpuMeshMemoryTargetMib (32MB), FIntSmoothTerrainPhysicsCacheSize (32MB), and FIntRenderTextureTotalBudgetMB (128MB). - Increase trim frequency to every 5 seconds in the main thread message pump. * fix(jnivm): preserve JNI reference lifetimes to prevent dangling string dereferences - Restore DeleteLocalRef and DeleteGlobalRef as safe no-ops to ensure Roblox JNI string lookups cannot cause SIGSEGV in __strlen_avx2. * perf(runtime): disable Luau startup GC suppression, triple GC sweep rate, and cap task arenas - Disable FFlagLuauStartupGcSuppression so loading garbage and temporary Roact reconciliation tables are purged immediately. - Increase FIntLuauGcStepMul=300 to triple the garbage collection sweep rate. - Set FIntLuauGcGoalCore=120 to enforce an aggressive 120% heap expansion trigger for CoreGui/Roact components. - Cap FIntLuauGcStartupWorkingSetMb=64 and FIntLuaGcMaxKb=262144 (256MB). - Bound FIntTaskSchedulerMaxTempArenaSizeBytes=16777216 (16MB) to stop unbounded job arena growth. * fix(audio): eliminate ReleaseTicket memory leak in OpenSL AbiClear and Shutdown - Delete all pending ReleaseTicket allocations when AbiClear is invoked instead of orphaning them indefinitely in state->pending. - Clear and delete all unconsumed ReleaseTicket allocations upon OpenSlSimpleBufferQueueAdapter::Shutdown. * perf(audio): replace dynamic OpenSL ReleaseTicket allocations with zero-alloc pool and cap thread stack to 256KiB - Preallocate ReleaseTicket array inside State sized to options.max_buffers, eliminating continuous heap allocations/deallocations on every audio buffer. - Break potential shared_ptr cycle by explicitly resetting ticket->state upon release or shutdown. - Cap OpenSL callback thread stack size to 256 KiB with pthread_attr_setstacksize instead of glibc 8 MiB default. * fix(audio): cascade OpenSL engine destruction to child players and track active objects safely - In OpenSL ES, destroying the SL_IID_ENGINE object must implicitly destroy all audio players and output mix objects created by it. Previously, child players were orphaned and leaked. - Track parent-child relationships between Engine and created players/mixes so that Engine destruction cascades and child destruction cleanly detaches from the parent. - Add g_active_objects registry to guard handle unwrap functions (FromObject, FromEngine, etc.) preventing use-after-free and double-destroy segfaults. - Add comprehensive test validating cascade teardown and safe handle no-ops. * perf(audio): bound sound memory and decode buffer caches - Set FIntProjectedMaxBytesUsedForSoundsMB to 32 MB to clamp Roblox sound heap. - Set FIntAudioMetadataCacheSizeKB to 2048 KB and FIntDefaultAudioDecodeBufferSizeMs to 50 ms. - Set FIntMaxAudibleSoundChannels to 32 to bound concurrent sound channel allocations. * perf(graphics): add mailbox present mode, disable MSAA, and support high-DPI scaling bypass - Default MESA_VK_WSI_PRESENT_MODE to mailbox for low-latency tear-free Wayland presentation. - Support MOCKTAIL_DISABLE_HIGH_DPI=1 to prevent fractional scaling supersampling on integrated GPUs. - Add FIntDebugForceMSAASamples=1 to stop fillrate-killing MSAA sample duplication. - Support MOCKTAIL_GRAPHICS_QUALITY override (defaults to 3, accepts 1..10 or 'auto'/'manual' to unlock the in-game Roblox settings slider). * fix(concurrency): resolve deadlocks in audio sink migration, OpenSL destruction, and command gate - Fix deadlock and use-after-free in SdlAudioSink when SwitchPlaybackDevice and Shutdown execute concurrently by adding shutting_down_ wake/bailout to migration and !switching_device_ condition to shutdown. - Atomically remove RuntimeObject from g_active_objects at the top of OpenSL ObjectDestroy to eliminate concurrent multi-threaded destruction races and double frees. - Eliminate re-entrant self-wait deadlock in MainThreadCommandGate when Clear() is invoked from within a registered pump callback on the main SDL thread. - Ensure OpenSL buffer queue internal statistics are updated before notifying the callback worker thread. * perf(assets): eliminate UGC mesh decimation hitching and throttle texture compositing - Disable FFlagMeshLodApplyGeomMeshOptimizer: prevents client CPU from computing real-time quadric mesh decimation for UGC assets/accessories. - Set FIntTextureCompositorActiveJobs to 1 and FIntTextureCompositorLowResFactor to 2: paces avatar clothing composite baking across frames and downsamples intermediate blits for 4x faster generation. - Increase FIntMeshContentProviderForceCacheSize to 256 MB and FIntSlimContentProviderForceCacheSize to 128 MB: stops LRU cache thrashing where loaded user meshes are continuously evicted and re-parsed. * perf(window): implement lock-free fast paths for ANativeWindow with atomic EGL alias tracking - Add atomic EGL alias presence flag (g_has_egl_aliases) to track when EGL surface aliases are active. - On standard Vulkan rendering paths (!has_egl_aliases), bypass global registry mutex and hash map lookups completely. - Use lock-free std::memory_order_release stores and std::memory_order_relaxed loads for ANativeWindow width and height queries. * Revert "perf(window): implement lock-free fast paths for ANativeWindow with atomic EGL alias tracking" This reverts commit df8e40476ce737ec543edf0c79af1e9b9ef5c8ff. * perf(vulkan): implement thread-safe lock-free dispatch and proc cache (up to 37x faster) - Replace global dispatch caches with thread_local generation-checked caches for queues, devices, and command buffers. - Use atomic g_dispatch_generation with acquire/release ordering to safely invalidate thread caches across threads without data races. - Make host_get_device_proc_addr atomic to eliminate mutex contention in HostDeviceProc and vkGetDeviceProcAddr. - Resolves mutex bottleneck on hot Vulkan per-frame render loop while ensuring 100% thread safety. * perf(core): cache tracing flags to eliminate thousands of getenv scans per second in event and JNI loops - Cache SdlEventTraceEnabled and WindowTraceEnabled in src/window/window.cc to avoid calling getenv 3 times per mouse motion and SDL event. - Cache TraceEnabled and StringTraceEnabled in src/jnivm/jnivm.cc to avoid getenv calls on every JNI method/field lookup. * perf(jnivm): lock-free method descriptors and eliminate dynamic_cast in string decoding - Store stable JniMethodDescriptor pointers inside jmethodID to make MethodName and MethodSignature lock-free direct pointer reads (36.8ns -> 0.3ns, 100x+ faster). - Eliminates taking g_jni_state_mutex 5 to 10 times per JNI method call. - Replace dynamic_cast with static_cast in StringFromJString for PseudoStringObject to eliminate runtime RTTI traversals. * perf(core): eliminate dynamic_cast in JNI string accessors and silence unbuffered linker stderr spew - Replace dynamic_cast with static_cast across all 6 JNI string accessors (StringChars, StringUtf16Chars, StringUtf16Length, StringModifiedUtf8Length, CopyStringRegion, CopyStringModifiedUtf8Region) to remove expensive runtime RTTI traversals. - Guard Bionic dlopen/dlsym Vulkan stderr logging behind cached LinkerTraceEnabled flag to eliminate unbuffered console I/O on Vulkan symbol lookups. * fix(jnivm, audio): prevent unbounded JNI object leaks and eliminate audio futex wakeups - Re-enable DeleteLocalRef, DeleteGlobalRef, and DeleteWeakGlobalRef with handle reference counting so temporary JNI objects, byte arrays, and strings are reclaimed immediately instead of leaking forever in g_object_storage and g_array_storage. - Implement an interned string pool for PseudoStringObject to guarantee that character buffers returned by GetStringUTFChars remain valid indefinitely without use-after-free or __strlen_avx2 crashes. - Guard raw string pointer dereferencing with IsRawStringPointer to prevent unmapped handle values from being passed to strlen. - Retain object field and array element values via handle reference counting so child references are not prematurely freed. - Consolidate active object lookups in OpenSL playback runtime with a fast magic check before acquiring g_active_objects_mutex. - Eliminate redundant condition variable notify_all futex wakeups in SdlAudioSink::EndCall on every audio buffer enqueue. * perf(runtime): optimize input pacing, Vulkan observation, buffer queue, and mouse scaling (priorities 1-5) - [Priority 1] Bypass PaceInputPump sleep when SDL event queue has pending events to eliminate input lag and frame stutter with high-polling-rate mice. - [Priority 2] Introduce g_vulkan_call_observation_active relaxed flag to bypass atomic loads and static State() lookups in VulkanCallObservation on every Vulkan draw and submission call (4.25x speedup). - [Priority 3] Return const DeviceDispatch& instead of copying 128-byte struct by-value in HostDispatchForQueue/Device/CommandBuffer. - [Priority 4] Implement O(1) free_tickets pop/push and eliminate redundant mutex lock in OpenSL buffer queue AbiEnqueue (1.58x speedup). - [Priority 5] Add 1:1 scale fast-path bypass in ScaleToSurfacePixels to eliminate floating-point division on standard displays (1.73x speedup). * fix(vulkan, sync): eliminate VK_NOT_READY acquire error and implement in-place guest futex primitives - Preserve guest infinite acquire wait (kHostImageAcquireUnthrottledTimeoutNs = UINT64_MAX) so vkAcquireNextImageKHR does not poll with 0 and return VK_NOT_READY (1) to the engine - Add infinite-timeout fallback in vkAcquireNextImageKHR and vkAcquireNextImage2KHR ensuring VK_NOT_READY is never leaked on infinite acquire requests - Replace shadow host synchronization tables with direct in-place guest futex words for sem_t, pthread_rwlock_t, pthread_once_t, and pthread_spinlock_t - Increase unthrottled swapchain depth to 5 buffers (PreferSwapchainMinImageCount) to prevent compositor acquire blocking - Add lock-free fast-path bypass for Vulkan queue submissions when text overlay compositor is inactive - Consolidate DrainPlatformEvents scoped locks and optimize input pump cadence --------- Co-authored-by: glook9001 <310372091+glook9001@users.noreply.github.com> Co-authored-by: komaruworld <rtysus228@gmail.com>
Mocktail
Mocktail runs the Android x86_64 Roblox client on Linux, including a Linux
userspace hosted by FreeBSD's Linuxulator. It provides the Android ABI and JNI
pieces the client expects, then connects them to SDL3 and Vulkan or OpenGL on
the Linux side.
Mocktail is an independent community project. It is not affiliated with Roblox Corporation or VinegarHQ and does not distribute the Roblox client.
How it works
Roblox APK -> signature and ABI checks -> Bionic + JNI -> SDL3 + Vulkan/OpenGL
The APK is checked before any native code is loaded. It is downloaded on first launch and is not bundled with Mocktail. The last working copy is kept in case an update fails.
Install with Flatpak
Install the stable release from Flathub:
flatpak install flathub space.bigrat.mocktail
flatpak run space.bigrat.mocktail
Nightly builds are produced automatically from the latest main branch:
flatpak install --user https://mocktail.bigrat.space/mocktail.flatpakref
flatpak run space.bigrat.mocktail
Install from the AUR
Arch Linux users can install either the pinned source release (mocktail) or
the current development version (mocktail-git) with an AUR helper:
paru -S mocktail-git
# or
yay -S mocktail-git
Use mocktail instead of mocktail-git to build the pinned release from
source, or install the stable prebuilt package with paru -S mocktail-bin or
yay -S mocktail-bin.
Install with DNF
Fedora 44 users can install either the stable mocktail package or the
mocktail-nightly package built from main:
sudo curl -fsSL https://mocktail.bigrat.space/rpm/mocktail.repo \
-o /etc/yum.repos.d/mocktail.repo
sudo dnf install mocktail
# or
sudo dnf install mocktail-nightly
Install with APT
Ubuntu 26.04 users can install either the stable mocktail package or the
mocktail-nightly package built from main:
sudo install -d -m 0755 /etc/apt/keyrings
sudo curl -fsSL https://mocktail.bigrat.space/mocktail-packages.gpg \
-o /etc/apt/keyrings/mocktail.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/mocktail.gpg] https://mocktail.bigrat.space/apt mocktail main" | \
sudo tee /etc/apt/sources.list.d/mocktail.list >/dev/null
sudo apt update
sudo apt install mocktail
# or
sudo apt install mocktail-nightly
Direct downloads
Direct AppImage, DEB, and RPM downloads are available from the Website and GitHub Releases.
FFlag overrides
Put a JSON object in $XDG_CONFIG_HOME/mocktail/fflags.json (usually
~/.config/mocktail/fflags.json). Mocktail applies it on the next launch.
{
"FFlagExample": "True",
"DFIntExample": "120"
}
FAQ
To see the most Frequently Asked Question go check FAQ.md
Building
Linux x86_64 is supported. Experimental FreeBSD 15.1 Linuxulator support has
been tested with an x86_64 Fedora 44 userspace. On FreeBSD, Mocktail runs
inside Linuxulator; it is not a native FreeBSD binary. Building requires CMake
3.20+, Git, pkg-config, LLD, binutils, a C++17 compiler, SDL 3.4+, SDL3_ttf,
Vulkan, EGL, libplacebo, fontconfig, libcurl, OpenSSL, libelf, libyaml, minizip,
Capstone 5, utf8proc, nlohmann/json, GTK4, libadwaita 1.6+, and WebKitGTK 6.0.
See the FreeBSD Guide for setup and launch instructions.
Ubuntu 26.04+
sudo apt update
sudo apt install build-essential cmake git ninja-build pkg-config lld \
libsdl3-dev libsdl3-ttf-dev libcurl4-openssl-dev libssl-dev \
nlohmann-json3-dev libyaml-dev libelf-dev libminizip-dev \
libcapstone-dev libgtk-4-dev libadwaita-1-dev libwebkitgtk-6.0-dev \
libutf8proc-dev libfontconfig1-dev libegl-dev libvulkan-dev \
libplacebo-dev zlib1g-dev
Arch Linux
sudo pacman -S --needed base-devel cmake git ninja pkgconf lld sdl3 sdl3_ttf \
curl openssl nlohmann-json libyaml libelf minizip capstone gtk4 \
libadwaita webkitgtk-6.0 libutf8proc fontconfig libglvnd \
libplacebo vulkan-headers vulkan-icd-loader zlib
Fedora 44+
sudo dnf install gcc-c++ cmake git ninja-build pkgconf-pkg-config lld \
SDL3-devel SDL3_ttf-devel libcurl-devel openssl-devel \
nlohmann-json-devel libyaml-devel elfutils-libelf-devel minizip-ng-compat-devel \
capstone-devel gtk4-devel libadwaita-devel webkitgtk6.0-devel \
utf8proc-devel fontconfig-devel libglvnd-devel vulkan-headers \
vulkan-loader-devel libplacebo-devel zlib-ng-compat-devel
git clone --recurse-submodules https://github.com/komaruworld/mocktail.git
cd mocktail
make build
./build/mocktail
Known limitations
Mocktail does not currently work with hardened_malloc. Using
hardened_malloc may cause Mocktail to fail to start or crash during runtime.
Run Mocktail without hardened_malloc enabled.
License
Apache License 2.0. Third-party components keep their own licenses.
Support
You can support the project by giving it a star or with cryptocurrency:
- USDT (TON):
UQCi6Yzcc9cOctoij6n_r1K90-OdVxAT0D_xo2UzGKkQaJDY - USDT (TRC20):
TNPMG9Vig2xiuo2r1QqnXRChPH7Vu28Jmx


