Pushing the Limits: Turning a 4GB Lenovo Duet Chromebook into My Primary Development Machine
DEV Community

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)

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.