The office fridge hates me and keeps freezing my carrots. I love carrots. They’re the perfect low calorie crunchy snack for those afternoons when you’re chasing an errant semicolon for two hours and your code isn’t working.

But they’re not very tasty frozen. In fact they’re disgusting when frozen.

You gotta thaw those suckers.

How do you thaw carrots at the office? With your laptop!

But sometimes that doesn’t work. Maybe you’re chasing that errant semicolon for so long that your computer cools down. Maybe webpack is actually fast for once. Maybe even VSCode and Chrome and XCode aren’t doing the job.

Never thought I’d say this, but sometimes macs just don’t wanna get hot no matter what you do.

So I built a tool! A node app. An app that thaws your carrots. Keeps your hands warm. In winter it might even heat your room.

The greatest contribution to computer science known to man! Or woman.

🥕 thaw-carrots -t 90

Install globally with npm or yarn – npm install -g thaw-carrots, run with your favorite temperature, and thaw-carrots will keep your CPU busy just enough to give you a nice even warm throughout your best carrot thawing areas.

Here’s how it works 👇

With just 14 dependencies this might be the smallest node app you’ve ever seen. Thanks to @lukeed05 and his obsession with zero dependency code. 

thaw-carrots uses mri to parse command line arguments, kleur and single-line-log for pretty console output, and systeminformationto read CPU temperatures.

The approach is simple:

  • run an infinite loop
  • read temperature
  • if temperature below target, add expensive background jobs
  • if temperature above target, remove an expensive job
  • print info
  • repeat

29 lines of code, 2 hours of tinkering

async function thawMyCarrots(targetTemp) {
    let temp = await readTemp(),
        temps = [temp, temp, temp],
        children = [];

    while (1) {
        if (avg(temps) < targetTemp) {
            if (children.length < 10) {
                children.push(fork(`${__dirname}/eat-cpu`));
            }
        } else if (avg(temps) > targetTemp) {
            if (children.length > 0) {
                children.pop().kill();
            }
        }

        temp = await readTemp();
        temps.shift();
        temps.push(temp);

        sll(
            "Current temp",
            kleur.bold.red(temp.main.toFixed(2)),
            "\nCores at",
            kleur.bold.gray(temp.cores),
            `\nChildren: ${children.length}`
        );
        sleep.msleep(500);
    }
}

We read the current CPU temperature, pre-fill our running tally of 3 measurements, and create an empty pool of children processes. Then start the loop.

The loop checks an average of the last 3 temperatures and decides what to do. If we have to warm up, we fork a new subprocess using the eat-cpu file. If it’s time to cool off, we kill one of the forks.

I kept max forks at 10 because that seemed reasonable.

Update our running array of temperature measurements, print current values to the screen, wait 500 milliseconds, do it all again. Perfect 👌

How to warm a CPU

To warm a CPU, you have to make it work. Like an athlete at the gym, the CPU gets warm when it’s working hard.

But what’s hard for a CPU?

You want a process that’s heavy on CPU and light on memory. Easy to spin up and down, make harder or easier. You want fine grained control over that temperature and you’re fighting everything your OS was designed to prevent.

The low memory requirement disqualifies calculating primes, playing with big numbers, mining bitcoin, or running Slack. You’d be surprised how many people recommended I just run Slack or Chrome or Hangouts to thaw my carrots.

Those fools!

My first attempt was using the collatz conjecture. Finite calculation, lots of addition and division and multiplication, handles big numbers okay, can run for a long time to find the full chain. No need to keep anything in memory while you’re running.

But my CPU was too good at that. Didn’t warm up for shit. And when the numbers got really high, Collatz fast became too slow to compute. Didn’t have the fine grained control.

Then I found this little gem from @sqren. A gist called “cpu-intensive.js”. Perfect!

Looks like this:

function mySlowFunction(baseNumber) {
    console.time('mySlowFunction');
    var result = 0; 
    for (var i = Math.pow(baseNumber, 10); i >= 0; i--) {       
        result += Math.atan(i) * Math.tan(i);
    };
    console.timeEnd('mySlowFunction');
    return result;
}

mySlowFunction(3);

I don’t know what it’s doing. It’s some sort of maths. But it runs good and strong with small inputs. It’s easy to spin up and down. And doesn’t keep anything in memory.

One wasn’t enough so I’m running up to 10 in parallel 🔥

🥕

You can see thaw-carrots on GitHub. Install via npm.

Can’t wait to try it at the office today. Nom!

Enjoy 🥕

Learned something new? Want to become a better engineer? 💌

Join 9,400+ people just like you already improving their skills.

Here's how it works 👇

Leave your email and I'll send you an Interactive Modern JavaScript Cheatsheet 📖 right away. After that you'll get a thoughtfully written email every week about React, JavaScript,  and lessons learned in my 20 years of writing code for companies ranging from tiny startups to Fortune5 behemoths.



Man, I love your way of writing these newsletters. Often very relatable and funny perspectives about the mundane struggles of a dev. Lightens up my day. ~ Kostas

PS: You should also follow me on twitter 👉 here.
It's where I go to shoot the shit about programming.