Big-O Operations and Runtime Estimator

Big-O tells you how work grows with input size; it does not tell you how long anything takes. This calculator closes that gap. Choose a complexity class, an input size and a constant factor, give it a machine speed in operations per second, and it returns the estimated operation count, the wall-clock runtime, the largest n that fits a time limit, and the factor by which the work multiplies when n doubles. It also reports the base-10 logarithm of the operation count, which stays meaningful for exponential and factorial classes where the count itself exceeds what a computer can represent.

Calculator

This calculator runs in your browser. Enable JavaScript for live results — the inputs, formula and worked example below remain fully readable without it.

Inputs this calculator takes, with typical values
InputWhat to enterExample
Complexity classLogarithms are base 2, which is the convention for algorithms that halve the problem.O(n²) — nested loop
Input size (n)The size the complexity is expressed in — array length, node count, number of records.100000 items
Constant factor (c)Operations performed per unit of f(n). Measure it by timing a known n and dividing, rather than guessing.1 ×
Machine speedSimple operations your machine completes per second. 10⁸ to 10⁹ is the usual working assumption for interpreted and compiled code respectively.1 ops/s
Time limitBudget used for the maximum-n figure. Competitive programming judges commonly allow one or two seconds.1 s

It returns

  • Estimated operations — c × f(n). Shown as ∞ when the count exceeds what double precision can hold — read the logarithm instead.
  • log₁₀ of the operation count — Always finite. An operation count of 10³⁰⁰ shows as 300 here.
  • Estimated runtime
  • Largest n that fits the time limit — The real solution of c·f(n) = rate × limit. Round down to a whole number of items.
  • Work multiplies by this when n doubles
  • Runtime at twice the input size
  • Operations per input element — The operation count divided by n — a useful sanity check against a profiler.

The formula

t=cf(n)R
g=f(2n)f(n)
log10N=log10c+log10f(n)

In plain text: operations = c · f(n); runtime = operations / R; max n solves c · f(n) = R · T

  • f(n)The growth function: 1, log₂n, n, n log₂n, n², n³, 2ⁿ or n! (operations)
  • cConstant factor — operations performed per unit of f(n) (×)
  • nInput size (items)
  • RMachine speed (ops/s)
  • TTime limit (s)
  • tEstimated runtime (s)

Big-O deliberately discards c and all lower-order terms, so it describes growth and not duration. Putting c back in is what turns an asymptotic statement into a number of seconds, and c is the term you must measure rather than assume.

Updated Category Computer Science, Data & Application Metrics Verified against published test cases Reading time 13 min

What big-O says and what it refuses to say

Big-O describes how the work an algorithm does grows as its input grows, and nothing else. Saying an algorithm is O(n²) means that beyond some input size the work is bounded above by a constant multiple of n². It says nothing about the constant, nothing about small inputs, and nothing about seconds.

That abstraction is exactly what makes the notation useful and exactly what makes it useless on its own. Useful, because the constant depends on the language, the compiler, the processor and the memory hierarchy, all of which change, while the growth rate is a property of the algorithm and does not. Useless on its own, because a question like “will this finish before the deadline” is a question about seconds.

Restoring the missing information takes two numbers. The constant factor converts units of f(n) into operations: a sort performing three comparisons and a swap per unit of n log n has a constant near four. The machine speed converts operations into seconds. Multiply and divide, and the asymptotic statement becomes a prediction you can test.

The prediction will be approximate, and the direction of error is usually the same. Real machines do not execute operations at a uniform rate: a sequential scan through an array runs many times faster per element than a pointer chase through a linked list of the same length, because one is served by cache and prefetching and the other is not. Quantify that gap with the cache hit ratio and AMAT calculator. What this calculator gives you is the order of magnitude, and for the decisions big-O is meant to inform, the order of magnitude is what settles the argument.

The classes, and how fast each one really grows

O(1) — the work does not depend on n. A hash lookup, an array index, arithmetic. Doubling n multiplies the work by 1.

O(log n) — the work grows by a constant amount each time n doubles. Binary search over a billion elements takes about 30 steps; over a trillion, about 40. Doubling n adds one operation, so the multiplier is 1 + 1/log₂n, which approaches 1 as n grows. Logarithmic algorithms are effectively free.

O(n) — doubling n doubles the work. Reading a file, summing an array, a single pass over records.

O(n log n) — doubling n slightly more than doubles the work: the multiplier is 2(log₂n + 1)/log₂n, which at n = 106 is about 2.10. This is the bound for comparison-based sorting, and in practice it behaves almost like linear.

O(n²) — doubling n quadruples the work. Nested loops over the same collection, insertion sort, the all-pairs comparison. This is the class where the transition from “fine in testing” to “unusable in production” happens, because a hundredfold increase in data is a ten-thousandfold increase in time.

O(n³) — doubling n multiplies the work by eight. Naive matrix multiplication, triple-nested loops, some dynamic programming formulations.

O(2ⁿ) — each additional element doubles the work. Enumerating every subset. The multiplier when n doubles is 2ⁿ, which is not a number you can reason about casually: at n = 64 doubling the input multiplies the work by 1.8×1019.

O(n!) — enumerating every permutation. Going from n to n+1 multiplies the work by n+1. 20! is 2.4×1018; 21! is 5.1×1019.

The last two are the reason this calculator reports a logarithm. Beyond about 21024 a double-precision number becomes infinity, and the operation count for O(n!) at n = 1,000 is around 102,568. The logarithm keeps the answer readable where the count itself cannot be printed.

Worked example: will an O(n²) join survive production?

A nested-loop join compares every record in one collection against every record in another of the same size. It works fine on a 1,000-record test fixture. Production has 100,000 records. Assume the machine performs 109 simple operations per second and the inner loop costs about 5 operations per pair, so c = 5.

  1. Test scale. f(1,000) = 1,000² = 106, so operations = 5 × 106 = 5×106, and runtime = 5×106 ÷ 109 = 5 ms. Nobody notices.
  2. Production scale. f(100,000) = 1010, so operations = 5×1010 and runtime = 5×1010 ÷ 109 = 50 seconds.
  3. Check the ratio. n grew by 100×, and 100² = 10,000, so the runtime grew from 5 ms to 50 s — exactly 10,000×. The arithmetic is self-consistent.
  4. What one more doubling costs. At n = 200,000 the work quadruples: 200 seconds.
  5. What fits in one second. The budget is 109 × 1 ÷ 5 = 2×108 units of f(n), so n = √(2×108) = 14,142. The algorithm supports about fourteen thousand records within a one-second budget.

Now compare the alternative. A hash join is O(n) with a larger constant — say c = 20, because hashing and probing cost more per record than a comparison. At n = 100,000 that is 20 × 100,000 = 2×106 operations, or 2 ms. It is 25,000 times faster than the nested loop despite having a constant factor four times larger.

The crossover is worth computing, because it is where the intuition “the simple algorithm is faster on small inputs” stops being true. Solve 5n² = 20n, giving n = 4. Above four records the hash join wins, and the four-times-worse constant buys the nested loop almost nothing.

How to read the result

Compare the operation count against 108 to 109, which is the range a modern machine completes in about a second for simple operations. Below 108 you are almost certainly fine; above 1010 you are almost certainly not; in between, the constant factor decides and you should measure rather than argue.

Use the doubling factor to plan for growth, because it is the number that tells you whether today's acceptable runtime survives next year's data. An O(n log n) pipeline that runs in ten minutes today runs in about twenty-one minutes at twice the data. An O(n²) pipeline runs in forty minutes. An O(n³) one runs in eighty. Those three futures need very different responses, and the difference is invisible in a single measurement of today.

Use the maximum-n figure when the budget is fixed. Competitive programming makes this explicit — a one-second limit and n ≤ 105 is a strong hint that the intended solution is O(n log n), because 105 × 17 is well inside a second while 1010 is not. The same reasoning applies to a request that must return within 200 ms.

Treat the constant factor as the thing you measure, not the thing you guess. Run the code at a known n, count or time the work, and divide by f(n). Do it twice at different sizes: if the derived constant is stable, your complexity assumption is right; if it grows with n, the real complexity is worse than you thought and the discrepancy tells you by how much. This is the single most useful thing you can do with this calculator, and it turns a rough estimate into a calibrated one.

Finally, remember that parallelism changes the constant, not the class. Sixteen cores can give you a sixteen-fold speedup at best and rather less in practice, which moves an O(n²) workload from fifty seconds to perhaps four — one doubling of n and you are back where you started. The Amdahl's law speedup calculator puts a ceiling on what parallelism can buy, and the ceiling is usually lower than people expect.

Operations by complexity class and input size

Values of f(n) with a constant factor of 1. Logarithms are base 2. Entries above 1018 are given in scientific notation because no machine will reach them.
f(n)n = 10n = 100n = 1,000n = 1,000,000
11111
log₂ n3.326.649.9719.93
n101001,0001×106
n log₂ n33.26649,9661.99×107
10010,0001×1061×1012
1,0001×1061×1091×1018
2ⁿ1,0241.27×10301.07×1030110301,030
n!3,628,8009.33×101574.02×102,567105,565,709

At 10⁹ operations per second, the n = 1,000,000 column reads: n log n takes 20 ms, n² takes about 17 minutes, and n³ takes about 31.7 years. Those three lines are the whole argument for caring about complexity.

Largest n that fits one second at 10⁹ operations per second

Each row solves f(n) = 109 with a constant factor of 1. Discrete classes are rounded down to a whole number of items.
ComplexityLargest n in 1 secondTypical algorithm
O(1)any nHash lookup, array index
O(log n)astronomically largeBinary search, balanced tree lookup
O(n)1×109Linear scan, counting sort
O(n log n)3.96×107Merge sort, heap sort, most practical sorts
O(n²)31,622Insertion sort, all-pairs comparison
O(n³)1,000Naive matrix multiply, Floyd–Warshall
O(2ⁿ)29Subset enumeration, naive SAT
O(n!)12Permutation search, brute-force TSP

Read the last two rows carefully: doubling machine speed adds one to the O(2ⁿ) limit and does not reliably add anything to the O(n!) limit. For exponential and factorial problems, hardware is not a lever.

Where this estimate goes wrong

  • Memory access is not one operation. A cache hit costs a few cycles and a main-memory miss costs a few hundred. Two O(n) algorithms can differ by a factor of ten purely on access pattern.
  • Big-O hides the constant, and the constant sometimes wins. Insertion sort beats merge sort on small arrays, which is why real sort implementations switch to it below a threshold of a few dozen elements.
  • Average and worst case can differ. Quicksort is O(n log n) expected and O(n²) worst case; a hash table is O(1) expected and O(n) when every key collides. Decide which case you are budgeting for.
  • Amortised is not per-operation. A dynamic array append is O(1) amortised, but the individual append that triggers a resize is O(n). That matters when the metric is tail latency rather than throughput.
  • n is not always the obvious quantity. Graph algorithms are usually expressed in vertices and edges together, and string algorithms in pattern and text length. A single n loses that structure.
  • Input and output cost real time. Reading ten million lines from disk can dominate a linear algorithm's entire compute budget. Size the transfer separately with the data transfer time calculator.
  • Compilers and interpreters differ by orders of magnitude. The same algorithm can be fifty times slower in an interpreted language. That is a constant-factor difference, so it moves the runtime and not the class.
  • The asymptotic bound may not apply at your n. Big-O describes behaviour for sufficiently large n, and some algorithms with excellent asymptotics have constants so large they never win at realistic sizes.

Key terms

O, Ω and Θ
O is an upper bound, Ω a lower bound, and Θ a tight bound that is both. Saying an algorithm is O(n²) does not claim it is ever that slow; Θ(n²) does.
Constant factor
The number of actual operations per unit of f(n). Big-O discards it by definition, and it is what determines whether an asymptotically worse algorithm is faster at your input size.
Amortised complexity
The average cost per operation over a sequence, where occasional expensive operations are spread across many cheap ones. A dynamic array append is O(1) amortised despite occasional O(n) resizes.
Crossover point
The input size at which two algorithms take the same time. Below it the one with the smaller constant wins; above it the one with the better growth rate does.
Pseudo-polynomial
An algorithm polynomial in the numeric value of an input rather than in the number of bits used to write it. The knapsack dynamic program is the standard example.

When complexity is not the right question

Complexity analysis answers “how does this scale”. Three other questions frequently matter more, and none of them is answered by a growth rate.

The first is where the time actually goes. Profiling routinely shows that the asymptotically dominant loop is not the bottleneck at real input sizes, because a constant-time operation inside it makes a network call. Measure before you optimise; an O(n²) loop over 200 items is 40,000 operations and takes microseconds.

The second is what the memory hierarchy is doing. Two algorithms with identical complexity can differ by an order of magnitude on access pattern alone, which is why array-of-structs versus struct-of-arrays and cache-oblivious layouts are worth as much as an algorithmic improvement in numerical code.

The third is how much concurrency helps. Parallelism divides the constant by the number of workers, up to the limit imposed by whatever fraction of the program is inherently serial — the ceiling that Amdahl's law makes precise. It never changes the complexity class, so it buys you a fixed factor once and then stops. Queueing behaviour under load is a separate question again, governed by the relationship between arrival rate, service time and concurrency that Little's law captures.

Where complexity is the right question, it is decisive in a way nothing else is. No constant factor, no hardware upgrade and no amount of parallelism rescues an exponential algorithm at n = 100. That is the case in which you stop tuning and change the algorithm.

Frequently asked questions

How long does an O(n²) algorithm take for n = 1 million?

About 1012 operations with a constant factor of 1, which at 109 operations per second is roughly 1,000 seconds — a little under 17 minutes. Multiply by your real constant factor: at c = 5 it becomes about 83 minutes. This is why quadratic algorithms are usually acceptable in testing and unacceptable in production, since the test fixture is typically a thousand times smaller and therefore a million times faster.

What input size can I handle in one second?

At 109 operations per second and a constant factor of 1: about 109 for O(n), 3.96×107 for O(n log n), 31,622 for O(n²), 1,000 for O(n³), 29 for O(2ⁿ) and 12 for O(n!). Competitive programming problems are usually designed so that the stated bound on n points at the intended complexity — n ≤ 105 means an n log n solution is expected, and n ≤ 20 means an exponential one is.

Is O(n log n) much slower than O(n)?

Not by much at realistic sizes. The log₂ factor is 20 at a million elements and 30 at a billion, so an n log n algorithm does roughly twenty to thirty times the work of a linear one — a constant-looking difference over any range you will meet, and often smaller than the difference between two implementations of the same algorithm. The distinction that matters is between n log n and n², which at a million elements is a factor of fifty thousand.

What constant factor should I use?

Measure it rather than guess. Run the code at a known input size, record the elapsed time, multiply by your machine's operations per second to get an operation count, and divide by f(n). Do it at two different sizes: a stable constant confirms your complexity assumption, and a constant that grows with n means the real complexity is worse than you assumed. A constant of 1 is a placeholder, not an estimate.

Why does the operation count show ∞ for large exponential inputs?

Because the count exceeds what a double-precision number can represent, which is about 1.8×10308. The base-10 logarithm output stays finite and gives you the answer: a value of 300 there means about 10300 operations. The calculator uses a log-gamma function for factorials so that even 1,000!, which is around 102,568, produces a readable figure.

Does big-O apply to memory as well as time?

Yes, and space complexity is analysed the same way. Merge sort is O(n log n) time and O(n) space; heap sort is O(n log n) time and O(1) extra space. Space is often the binding constraint in practice, because exceeding physical memory causes swapping that costs several orders of magnitude more than any arithmetic. Substitute bytes per unit of f(n) for the constant factor to use this calculator for memory.

Will faster hardware fix an exponential algorithm?

No. Doubling machine speed adds exactly one to the largest n an O(2ⁿ) algorithm can handle, and a thousandfold speedup adds about ten. For O(n!) it is worse still, because going from n to n+1 multiplies the work by n+1 rather than by 2. When a problem is exponential, the answer is a better algorithm — dynamic programming, branch and bound, an approximation with a proven error bound, or a heuristic with measured behaviour.

Why is my measured runtime worse than this estimate?

Most often because memory access dominates. The estimate treats every operation as equal, while a main-memory access costs a couple of hundred cycles and a cache hit costs a few. An algorithm with poor locality — pointer chasing, random access into a large array, a linked list traversal — can run an order of magnitude slower than the operation count suggests. Garbage collection, interpretation overhead and input/output are the other common causes.

What is the difference between O and Θ?

O is an upper bound and Θ is a tight bound. Every O(n log n) algorithm is also correctly described as O(n²), because an upper bound remains valid if you loosen it — which is why quoting O alone can understate an algorithm's speed. Θ(n log n) asserts that the algorithm is both no worse and no better than n log n up to constants. Informal usage almost always means Θ when it says O.

References

  • Introduction to Algorithms, 4th edition, Cormen, Leiserson, Rivest and Stein — MIT Press
  • The Art of Computer Programming, Volume 1: Fundamental Algorithms, 3rd edition, D. E. Knuth — Addison-Wesley
  • Algorithms, 4th edition, Sedgewick and Wayne — Addison-Wesley