What watching the pasteboard costs
macOS publishes no notification when the clipboard changes. There is no callback to register, so every clipboard manager polls. It reads one integer, NSPasteboard.general.changeCount, a few times a second, and compares it to the last value it saw. If the number has not moved, nothing happens at all.
That is the entire watching mechanism. If a manager costs you real CPU while you are not copying, the polling is not the reason.
Work only starts when the number changes. That work is reading the pasteboard, deciding what type the content is, and writing it somewhere. It happens once per copy, and copies are rare on the scale a CPU cares about.
Where the cost actually hides
Images. A screenshot is a few megabytes. Store those bytes inside the database next to your text rows and the file grows fast. Every query then drags more data around, and reads get slower as the history fills.
Getting this right took me longer than any other part of the app. Making a pasted image survive a restart at all was harder than it looks. The working answer was to keep image bytes in separate files named by their hash, deduplicated, with the database holding only a reference.
Hashing and writing on the wrong thread. Once images go to files, something has to hash several megabytes and write them to disk. Do that on the main thread and you have built a stutter into the act of copying, which is the one moment the user is watching. That path has to move off the main thread for anything large, and the pasteboard read itself has to stay on the main thread, because it is not thread-safe. Splitting those correctly is fiddly.
My own history window reads one page at a time out of the database, with the search and the filters pushed down into the query. An earlier version loaded an index of everything into memory first, which was fine at a few hundred items and awful at several thousand.
Two separate numbers matter for this. How many clips the popup keeps in memory, and how many the database keeps on disk. Confusing them is how a manager ends up holding your whole history in RAM to draw a list of ten rows.
Text recognition. Reading text out of every copied image costs real CPU, on the copy, whether or not you will ever search for that text. Doing it on demand instead of on every copy is the difference between a feature and a tax.
Rich text. Parsing HTML into styled text on macOS goes through an old WebKit-based importer. The first call in a process loads that whole framework, so the first rich preview after launch is noticeably slower than every one after it. The fix is unglamorous: warm it up quietly after launch, then cache the result per item.
Cleanup on the hot path. My own worst offender. A maintenance pass that looked for orphaned image files was being called from the retention routine, which ran on every single copy. It scanned every stored item and every file in the blob folder to find files nothing referenced. With a full history, that added a visible delay to copying, every time. It now runs at launch and when you clear the history, and nowhere near a copy.