While everyone is pushing the limits of AI, I've been busy pushing the limits of a Lenovo Duet Chromebook tablet I inherited from my son. He used it as a school tablet for a year, but eventually got frustrated with its performance under their heavy workload. The tablet comes with just 4GB of RAM, but as a Chromebook, it has the unique ability to run both Android and Linux software.
I've been trying to move to a portable, lightweight development machine for the past 5+ years. After experimenting with (and eventually giving up on) Android and Termux paired with a Bluetooth keyboard, I decided to give this Duet a serious shot. This article covers my journey optimizing this 4GB tablet into my primary development machine—one that I use both on the go as a tablet and docked via USB-C to a larger monitor, keyboard, and mouse.
Step 1: Ditching the Android VM (ARC++)
The very first thing I did was disable the Android VM. I simply didn't have a use for Android apps on a dev setup. Disabling Android (ARC++) reclaims about 1GB of RAM immediately, which is a massive 25% gain on a 4GB device.
One minor hiccup: I briefly regretted this when it broke my Android-based Tailscale configuration. Luckily, I solved this by running Tailscale directly inside the Linux container using its userspace networking mode and SOCKS5 proxy:
tailscaled --tun=userspace-networking --socks5-server=localhost:1055
Step 2: Fine-Tuning Chrome Flags & Settings
Next, I tweaked a specific set of ChromeOS flags to maximize memory savings, force GPU acceleration across both Chrome and the Linux container, and stop Chrome from wasting CPU cycles and RAM prefetching pages:
-
Memory Saver Mode (
chrome://settings/performance): Set to Maximum. Automatically discards inactive background tabs. -
#ignore-gpu-blocklist→ Enabled: Overrides built-in software rendering blocklists to force GPU hardware acceleration across the OS. -
#enable-gpu-rasterization→ Enabled: Uses the Mali GPU to rasterize web content instead of the ARM CPU. -
#enable-zero-copy→ Enabled: Forces raster threads to write directly to GPU memory tiles, bypassing staging buffers in RAM. -
#crostini-gpu-support→ Enabled: Ensures hardware GPU acceleration is passed through directly into the Linux container. -
#scheduler-configuration→ Enables Hyper-Threading on relevant CPUs: Tunes CPU thread scheduling to maximize performance for active workloads. -
#enable-parallel-downloading→ Enabled: Accelerates download speeds by splitting files into parallel chunks. -
#prerender2&#prerender2-cross-origin-iframes→ Disabled: Prevents Chrome from speculatively pre-loading linked pages and third-party iframe embeds in hidden background processes. This saves 100MB–250MB of RAM and stops background CPU spikes while browsing.
Step 3: Optimizing Virtual Memory & Crosh Swap
ChromeOS uses ZRAM (compressed memory swap). By default, Linux container swappiness is set higher than ideal, causing active terminal tools to get pushed into swap too early.
-
Crosh ZRAM Swap: Opened Crosh (
Ctrl+Alt+T) and expanded the ZRAM swap limit to 8GB to give the system plenty of breathing room during heavy multitasking:
swap enable 8192
-
Linux Swappiness: Created
/etc/sysctl.d/99-custom.confinside Linux and added:
vm.swappiness=20
vm.vfs_cache_pressure=150
vm.overcommit_memory=1
This keeps active CLI processes in physical RAM while allowing smooth swapping when under memory pressure.
Step 4: Streamlining the Linux Container (Headless CLI Mode)
Since I don't use Linux GUI apps or Linux audio, I wanted to strip out background overhead.
-
Crucial Discovery regarding
sommelier: I initially tried to disablesommelier(the Wayland/X11 proxy display service), but the terminal crashed and Termina failed to start. In ChromeOS,sommeliermanages the host-to-container IPC sockets. Leavesommelierrunning! -
Masking PipeWire & PackageKit: I tried disabling
pipewireandpackagekit, but they kept restarting. The trick insystemdis that socket-activated services will automatically respawn whenever their socket is triggered. Usingmaskinstead ofdisablepermanently stops them:
# Mask PipeWire audio services & sockets
systemctl --user stop pipewire.service pipewire-pulse.service wireplumber.service filter-chain.service pipewire.socket pipewire-pulse.socket 2>/dev/null
systemctl --user mask pipewire.service pipewire-pulse.service wireplumber.service filter-chain.service pipewire.socket pipewire-pulse.socket 2>/dev/null
# Mask PackageKit (APT background update checker)
sudo systemctl stop packagekit 2>/dev/null
sudo systemctl mask packagekit 2>/dev/null
Conclusion
After this round of optimizations, I can happily say that I'm using the Lenovo Duet as my primary development machine. It easily handles AI harnesses, terminal code editors (like Neovim/Micro), and web browsing.
If you prefer VS Code, I recommend running VS Code Server inside Linux and accessing the editor interface directly through the Chrome browser:
code serve-web
This gives you the full VS Code experience without incurring the heavy RAM overhead of the Linux GUI container stack!
Top comments (0)