Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

COP 707: Coprocessor Execution

COP 606 showed what a cop task reads, and COP 706 showed how the unified read pool executes it. This chapter follows a task while it runs: how a scan gives other tasks a turn, when a long request is limited, and how TiKV separates waiting time from execution time.

Yielding While Scanning

A cop task reads its requested key ranges by asking a RocksDB iterator for keys. Each iterator call is synchronous. Once one begins, YATP cannot interrupt it, so the cop Future must return control voluntarily before another ready task can use the same worker.

Opening a new range can mean a separate point lookup, or positioning an iterator for an interval scan. A request may contain many one-key ranges, so TiKV checks time at every range boundary as well as periodically during a continuing scan:

Scanner stateCheck elapsed time
First key from a new rangeImmediately after it returns
Continuing in one rangeAt every 32 returned keys

At either checkpoint, TiKV compares the elapsed time with 1 ms:

elapsed time <= 1 ms  -> continue scanning
elapsed time >  1 ms  -> reschedule().await -> resume in a later poll

The timer starts with the scan and resets only after a yield. The first rule forces a time check, not a yield; a continuing scan avoids checking the clock for every key.

The 1 ms target is not a strict upper bound. TiKV can check only after a synchronous RocksDB operation has returned, so a slow lookup or block read can make one poll run longer.

Limiting Long Requests

TiKV applies a separate concurrency limit to unary cop handlers when the endpoint concurrency limit is enabled. A permit is one slot under that limit. TiKV first lets a handler run without one, while accumulating only the time spent actively polling it.

active handler polls total <= 5 ms  -> poll without a permit
still Pending after total > 5 ms    -> acquire a permit before the next poll

If no permit is available, waiting for it returns Pending, leaving the YATP worker free for another ready task. A request that finishes in the poll that crosses 5 ms needs no permit: it has no further poll to run.

The limiter therefore targets handlers that keep consuming worker time across polls. It does not choose which ready task YATP runs next.

Reading the Timing

TiKV's coprocessor tracker records the boundaries around a unary request's handler:

  • Schedule wait runs from preparing the request until its first read-pool poll.
  • Snapshot wait runs from that first poll until the Region snapshot is ready.
  • Process time is time spent polling that handler's Future.
  • Suspend time is time between handler polls after the Future has returned Pending.

The tracker sums process time across all handler polls. These boundaries distinguish delay before execution starts, snapshot acquisition, active handler work, and time spent waiting after the handler yields.