Pushing the Limits: Turning a 4GB Lenovo Duet Chromebook into My Primary Development Machine
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.conf inside 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,sommelier manages the host-to-container IPC sockets. Leavesommelier running! - Masking PipeWire & PackageKit: I tried disabling pipewire andpackagekit , but they kept restarting. The trick insystemd is that socket-activated services will automatically respawn whenever their socket is triggered. Usingmask instead ofdisable permanently 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)
Comments
No comments yet. Start the discussion.