Recommended Free Tools
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Calculate characters per second (CPS) by dividing a clearly defined character count by elapsed time in seconds. In a browser, measure elapsed time with performance.now(), convert milliseconds to seconds, and use total characters divided by total time when combining runs of different lengths.
What counts as a character in JavaScript?
JavaScript’s string.length returns the number of UTF-16 code units, not necessarily the number of Unicode code points or characters a person perceives. Those measures can differ: a supplementary Unicode code point uses two UTF-16 code units, and a visible grapheme can contain multiple code points.
Choose the unit that matches the metric your application promises:
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →| Counting rule | JavaScript approach | What the count means |
|---|---|---|
| UTF-16 code units | text.length |
The string’s length in JavaScript code units; some visible symbols count as more than one. |
| Unicode code points | [...text].length |
The number of code points yielded by iteration. This still may count a multi-code-point visible symbol more than once. |
| Grapheme clusters | new Intl.Segmenter(locale, { granularity: "grapheme" }) |
A practical count of user-perceived text units, according to locale-sensitive segmentation. |
For example, a flag emoji may be composed of multiple code points but displayed as one grapheme. MDN describes Intl.Segmenter as enabling locale-sensitive segmentation into meaningful items such as graphemes. It is marked Baseline 2024, so older browsers and devices may not support it. Unicode grapheme boundaries are a useful convention, not a universal definition of a character; implementations can tailor segmentation to orthographic conventions or user preferences.
#1 Best Overall
If you use grapheme counts, document the locale and runtime assumptions. Do not switch between code units, code points, and graphemes while comparing results.
How do you calculate CPS for one run?
Let count be the chosen text count and let durationMs be the elapsed duration in milliseconds. Convert the duration to seconds before dividing:
durationSeconds = durationMs / 1000
cps = count / durationSeconds
For browser timing, subtract the start reading from the end reading returned by performance.now(). The result is in milliseconds; dividing the count directly by that number would produce characters per millisecond, not CPS.
function calculateCps(count, durationMs) {
if (!Number.isFinite(count) || count < 0) {
throw new RangeError("count must be a finite, non-negative number");
}
if (!Number.isFinite(durationMs) || durationMs <= 0) {
throw new RangeError("durationMs must be a finite, positive number");
}
return count / (durationMs / 1000);
}
const startMs = performance.now();
// Run the measurement interval here.
const endMs = performance.now();
const cps = calculateCps(text.length, endMs - startMs);
The validation is part of the calculation logic: a zero or invalid duration cannot produce a meaningful finite rate. If your application should show an error rather than throw, handle that outcome at the call site. The example uses text.length; replace it with the chosen code-point or grapheme count when that is the product’s definition.
Rank #3
Why use performance.now() for elapsed time?
performance.now() returns a high-resolution timestamp in milliseconds relative to a monotonic time origin. It is designed for measuring elapsed intervals and is not affected by system clock adjustments. MDN explains the distinction in its Performance: now() method reference.
Date.now() returns milliseconds since the Unix epoch, which is useful when you need a wall-clock timestamp. It can be affected by system clock changes, so it is generally a poorer choice for measuring a browser interval. MDN documents its behavior in the Date.now() reference.
Rank #4
Timer precision can be reduced by browser privacy and security protections. Browser behavior can also differ on whether the performance clock advances while the operating system is asleep. For ordinary short intervals, performance.now() is the appropriate elapsed-time source; for long measurements that may span sleep, define whether sleep time belongs in the measured duration.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →How should you combine runs with different durations?
For runs with counts cᵢ and durations tᵢ in seconds, calculate the overall rate from totals:
Best Value
aggregate CPS = Σcᵢ / Σtᵢ
This is equivalent to a duration-weighted mean of the individual run rates. A run lasting longer contributes proportionally more time and count. The simple arithmetic mean of run-level CPS values gives every run equal weight instead, so it answers a different question when durations vary.
function aggregateCps(runs) {
const totalCount = runs.reduce((sum, run) => sum + run.count, 0);
const totalDurationMs = runs.reduce((sum, run) => sum + run.durationMs, 0);
return calculateCps(totalCount, totalDurationMs);
}
Use this aggregate when the desired result is the rate across all measured time. If you instead want each attempt to have equal influence regardless of duration, calculate and label the unweighted mean explicitly.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.How can you make a CPS measurement repeatable?
Keep the arithmetic separate from clock access. A pure function that accepts a count and duration can be tested with fixed values, while live measurement code supplies readings from performance.now().
Free tools Windows power users keep installed
One-click scans. No signup required.
- Fix the input text. Use the same exact string for each comparison and record it with the result.
- Declare the counting rule. State whether you count UTF-16 code units, code points, or grapheme clusters; note locale and runtime where relevant.
- Define the interval. Specify when timing starts and ends, and whether pauses are included. Excluding pauses measures active rate; including them measures elapsed-session rate.
- Test arithmetic with fixed values. Pass predetermined counts and durations to the pure calculation function instead of relying on a live clock in unit tests.
- Keep live timing at the boundary. Read
performance.now()when the measured interval begins and ends, then pass the difference into the calculation.
These choices make the result interpretable: changing the text, count definition, pause policy, or timing interval changes what the reported CPS means.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

