Tuesday, April 19, 2022

Anki Backlog Hell

 People have written about Anki Ease Hell:

But there is another kind of hell with Anki, which I call Backlog Hell.

Backlog Hell results from two features of Anki:

  1. Cards are presented in the order they are due
  2. New cards are presented regardless of backlog

When you have a backlog of due cards, you do not see them promptly when they are due. This isn't an issue with a small backlog but becomes an issue with a larger backlog.

Consider what happens if you are reviewing about 1,000 cards per day and you take a break from study for a week. You may take a break because you have exams, vacation, work or illness. It doesn't matter why. When you return, how many cards do you have due? After one week, you will have about 7,000 cards due for review. Maybe a bit less: some of those cards are short interval.

You normally are reviewing 1,000 cards per day.  Maybe this takes you 30 minutes per day (about 2 seconds per review if they are quick) or maybe 2 hours per day (about 8 seconds per review if you take a bit more time on each card).

To get through your backlog, you might be able to double your study time. If you do, you can review 2,000 cards per day instead of your usual 1,000 cards. You should clear your backlog quickly, right? In one week, you should have cleared your backlog, right?.

Wrong! it will take much more than 1 week to clear your backlog. It might never happen. Instead, your backlog might get larger every day.

If you know your cards well (i.e. they are almost always Good or Easy, even if you don't see them promptly) then you will clear your backlog.

If a card has an interval of 100 days and you see it after 107 days, it doesn't make much difference. If it was going to be Good at 100 days, it will probably be Good at 107 days. You will clear these from your backlog. Even if you don't get to it the first day it is due. Seeing them after 114 or 120 days isn't too much different from 100 days. Not optimum, but often you will still remember.

But what about the cards that you were just learning: the majority of your daily review? What happens to a card that you should have reviewed after 7 days? You will not see it again for at least 14 days, maybe longer. Will it still be Good after two or three weeks?

You end up clicking Again. You should see these cards again soon. But you still have a backlog, so you don't see it until you have seen all the other cards in your backlog. Maybe not for a few days or weeks.

You continue reviewing cards long after they were due. Can you recall them, long after they were due? Sure, sometimes you will. But if the scheduling algorithm is good, seeing them long after they were due will not be as effective as seeing them when they were due: the whole point of the scheduler is to present them at the optimum interval: shorter or longer intervals are sub-optimum.

So, just when you need to optimize your study: to clear the backlog as quickly as possible - Anki goes into a sub-optimal mode.

If your backlog is too big, it will be so sub-optimal that you can't catch up.

And Anki adds new cards every day. What happens to a new card added today? You should see it again in a few minutes, or maybe tomorrow. But when do you see it?

Because Anki presents cards according to due date and all the cards in your backlog were due before today, you will not see that new card again until you have reviewed all the cards in your backlog. If you have 7,000 cards in your backlog and you can review 2,000 per day, that's over 3 days until you can see that card again.

Can you learn your new cards if you only see them once every 3 days? How about once a week? Or once a month? If I wasn't doing anything else, maybe I could. But when I am reviewing 2,000 cards per day, I can't. It comes up again in a few days but I should have seen it again in 10 minutes. I can't remember it. So I click Again. It is due in 10 minutes but there are still 7,000 cards that I have to review first, before I will see it again. And I can't review 7,000 cards in 10 minutes, so I see it late again: days late.

And still Anki makes the problem worse by adding more new cards every day.

Seeing cards significantly after their due date, your learning will be sub-optimal.  With a small backlog: no problem. With a large backlog: you will never catch up. You will study more and more but see your backlog get a bit bigger each day. Remember: you were studying 1,000 cards per day. Some of these were short interval cards but some were long interval cards: there will be more of these added to your backlog each day. 

Eventually, you will stop learning almost completely: forever reviewing but never progressing: a Sisyphean torment: Backlog Hell.

Every time you see a card that you can't remember, because you haven't seen it in too long and you are overloaded, you click Again. Doing that a few times sends you into Ease Hell.

Ease Hell is bad enough, but combine it with Backlog Hell and you are doomed to failure. Your backlog will grow. You will never catch up. You will spend more and more time to learn less and less. When you don't see your cards on time: when you see your new cards days late, you will not learn effectively.

How to escape Backlog Hell?

First, manually reduce your new cards per day to 0. There is no point adding to the problem. You can start learning new cards again after you clear your backlog.

Then, study only a subset of cards each day. You can study select decks or create custom decks. Your objective should be to review cards on time. You need to optimize your learning to get through the backlog.

It is better to review some cards on time and learn them than it is to review all your cards (or as many of them as you can review in a day) days or weeks late and not learn any of them.

With no new cards being added, if you continue learning effectively you should eventually clear your backlog.

Alternatively, you can set all the cards in your backlog back to new. Then they will be re-introduced gradually, according to your new card limit.

But, do you really want to set 7,000 cards back to new? That's tremendous setback: another torment.

I ended up giving up on Anki. I didn't want to reset all my cards to new or other manual workarounds, and I didn't want to forever be in Ease Hell and Backlog Hell. I wanted to learn and I wanted to spend my time learning, not fussing with Anki. I couldn't fix the Anki scheduler so I wrote srf. I still take occasional breaks from study and have backlogs. It still takes time to clear a backlog, but I make reliable progress and I don't have to fuss with the scheduler: it just works. 

On the other hand, the srf scheduler is easy to change if I want to: there are parameters for minor adjustments and it is just some JavaScript and SQL queries, if I want to make more fundamental changes. I have changed it several times since first writing srf. It is quite different from Anki in its details, though similar in its principles and objectives. It is now settled to something I am quite comfortable with and a vast improvement over the Anki scheduler.

Wednesday, April 13, 2022

Testing Express based apps

All of the examples of automated testing Express based apps that I have found use supertest. But supertest is based on superagent and I don't like the API of superagent and, therefore, supertest.

But it is not necessary to use supertest. All it does is run an instance of the app and submit queries to it, then muddle assertions with the HTTP client. It is easy, more flexible and cleaner to run the app directly then use whatever means to submit requests and assert assertions: hopefully from independent packages.

For example:


'use strict';

const t = require('tape');
const app = require('../app');
const http = require('http');
const axios = require('axios');

const server = http.createServer(app);
server.listen(0, '127.0.0.1');
server.on('listening', () => {
  const addr = server.address();
  const address = addr.address;
  const port = addr.port;
  console.log('addr: ', addr);
  console.log('listening on ' + address + ':' + port);
  runTests(port)
  .then(() => {
    server.close();
  })
  .catch(err => {
    console.log('tests failed with: ', err);
  });
});

function runTests (port) {
  return new Promise((resolve, reject) => {
    const request = axios.create({
      baseURL: 'http://localhost:' + port + '/'
    });

    t.test('GET / returns 200', (t) => {
      request({
        url: '/',
      })
      .then(res => {
        t.equal(res.status, 200, 'Status is 200');
      })
      .catch(err => {
        t.fail(err);
      })
      .finally(() => {
        t.end();
      });
    });
 

    t.onFinish(() => {
      resolve();
    });

    t.onFailure(() => {
      reject(new Error('something went wrong'));
    });
  });
}


This is simple enough: almost as simple as using supertest, and it has advantages:

  • Use any http client code you like
  • Use any assertion library you like

 

Labels