Time Complexity vs. the Nature of Time
Series: A Programmer’s Philosophical Reflections #04/11 | Reading time: 25-30 min | Concept: Philosophy of Time — Existence, Change, and Irreversibility
Author: Wina @ Code & Cogito
The 3 AM Countdown
It was the night before a major release.
The whole team stared at the deployment progress bar. Numbers scrolling across the terminal like some cryptic countdown. I glanced at the clock: 02:47. Felt like half a lifetime had passed.
“How long?” the PM asked.
“About three minutes,” I said.
In those three minutes, I reviewed the rollback script, checked the monitoring dashboard twice, drank half a cup of cold coffee. They lasted longer than three hours of a normal workday.
Deployment complete. Green lights across the board. 02:51.
“Only four minutes,” the PM laughed. “Felt like forty.”
I smiled grimly. Then I noticed something —
The “four minutes” we had just lived through involved at least three different kinds of time operating simultaneously.
CPU time: billions of clock cycles, precise to the nanosecond. The server didn’t feel anxious or hopeful; it simply executed each instruction faithfully.
Wall-clock time: from 02:47 to 02:51, four minutes flat. A physical measurement, indifferent to your feelings.
And the time inside us: stretched by anxiety, warped by stress, inflated by uncertainty into something that felt close to eternity.
Programmers work with time every day. We use Big-O to predict an algorithm’s future. We use timeouts to set the limits of waiting. We use cron jobs to carve up day and night. But we rarely stop to ask a more fundamental question:
What is time, actually?
Is it a resource — something you “spend,” “save,” or “waste”? Or is it not a “thing” at all, but merely our way of describing change?
This is the fourth article in the “A Programmer’s Philosophical Reflections” series. Starting from the time complexity you use every day, we’ll dive into the deep end of the philosophy of time.
Let’s debug time itself.
Background: How We Quantify Time, and What Gets Lost
Big-O: The Abstract Language of Time
Every programmer learns Big-O notation when studying algorithms. It’s elegant, concise — a function that describes “how bad things will get”:
# O(1): No matter how big the input, time stays constant
def get_first(arr): return arr[0]
# O(n): Linear growth
def find(arr, target):
for x in arr:
if x == target: return True
# O(n^2): Quadratic growth -- where disaster begins
def bubble_sort(arr):
for i in range(len(arr)):
for j in range(len(arr)-1):
if arr[j] > arr[j+1]: arr[j], arr[j+1] = arr[j+1], arr[j]
Big-O describes the shape of growth — when input scales from 1,000 to 1,000,000, how does the cost expand? It’s a prophecy about the future: if your data keeps growing, when will your system buckle?
But notice: Big-O isn’t about “time” per se. It’s about “workload” as a function. O(n log n) won’t tell you how many seconds a sort takes — it tells you that when data volume doubles, sorting will take “roughly a bit more than twice” the effort.
It’s a language of scale, not a language of existence.
Wall-Clock Time: The Physical World’s Referee
In engineering, we also care about another kind of time — wall-clock time, the duration users actually experience. Your algorithm might be O(n log n), but if the network adds 200ms of latency, the database query stalls for 3 seconds, and a CDN cache miss costs another 1.5 seconds — what the user feels is the sum of all those delays, not how elegant your algorithm is.
def total_latency(compute_ms, network_ms, db_ms, queue_ms):
"""What the user experiences = sum of all delays"""
return compute_ms + network_ms + db_ms + queue_ms
Wall-clock time is a merciless referee. It doesn’t care about the elegance of your code — only about how long the user waited.
Subjective Time: Humanity’s Time Bug
Then there’s the third kind — the hardest to deal with.
The same 10 seconds of waiting: on a blank white loading screen, it feels like a minute; with a progress bar and a friendly animation, it feels like five seconds; in the middle of a coding flow state, half an hour feels like five minutes.
Psychological research shows that human time perception is influenced by at least three factors: feedback (do you know the progress?), control (can you cancel or interact?), and emotion (are you anxious or engaged?). UX designers have known this forever — the progress bar doesn’t exist to show real progress. It exists to reshape your experience of time.
These three layers of time — algorithmic time, physical time, subjective time — coexist in engineering practice. But philosophers ask a question more fundamental than any of them: beneath all three layers, what is time itself?
The Philosopher’s Time Battlefield
Two major camps have fought over the nature of time throughout the history of philosophy.
Absolute time — Newton’s position. Time is the background container of the universe, flowing uniformly, unaffected by anything. Even if the universe contained nothing, even if nothing happened, time would still tick second by second. It’s like an infinite timeline on which all events are arranged.
Relational time — Leibniz’s position. Time is not an independently existing container but an abstraction of the relations between events. If nothing happens in the universe, “time” has no meaning. Time is merely our way of describing “before and after” and “change.”
For programmers, these two positions correspond to two design patterns you know well:
Newton’s time is like a global clock — System.currentTimeMillis(), always ticking regardless of what your program is doing. Leibniz’s time is like an event-driven architecture — no events, no time; time is simply an ordering tool for event sequences.
Einstein’s relativity ultimately supported something closer to Leibniz’s view: time is not absolute. Its flow rate depends on gravity and velocity. Clocks on GPS satellites run faster than those on the ground — without correction, your navigation would drift by about 10 kilometers per day.
Time is not the background. It’s part of the system.
Three Time Models: From Algorithms to Existence
One: Big-O Predicts the Shape of the Future, Not the Feel of the Present
Let’s take a hard look at what Big-O actually does.
When you say an algorithm is O(n^2), you’re saying: “As input scale grows, the cost of this algorithm expands at a quadratic rate.” This is a statement about trend, not about this moment.
Philosophically, this maps to an important distinction: temporal order versus temporal moment.
Big-O cares about temporal order — how things “change as input changes.” It never answers “what time is it now.” It answers “if things continue like this, what happens?” It’s a structural prediction about the future.
The ancient Greek philosophers had a similar division. Aristotle defined time as “the number of change with respect to before and after” — time is the tool we use to measure change, not an entity independent of change. If the world were perfectly static, with no change at all, “time” in Aristotle’s framework would lose its meaning.
This aligns astonishingly well with Big-O’s logic: if input size doesn’t change (no change), Big-O has nothing to describe. No change, no time complexity.
But engineers know Big-O has a massive blind spot: it abstracts away constants. An O(n) operation might take 0.001 seconds or 10 seconds — Big-O doesn’t care. It’s about structure, not experience. And we live in experience, not in asymptotic analysis.
Two: Synchronous and Asynchronous — How Waiting Rewrites the “Texture of Time”
One of engineering’s deepest insights about time: the same span of physical time can feel completely different depending on how you wait.
A synchronous call is blocking — you send a request, and your entire program halts there, unable to do anything else until the response arrives. Like standing in line at a counter, staring at the person ahead of you, unable to do anything else.
An asynchronous call is non-blocking — you send a request, go do other things, and handle the response when it arrives. Like ordering at a restaurant, getting a number, going shopping, and coming back when your number is called.
# Synchronous: you're locked into waiting
response = http.get(url) # The whole world pauses
process(response)
# Asynchronous: you retain freedom while waiting
future = async_http.get(url) # The world keeps turning
do_other_work()
response = await future
Philosopher Henri Bergson drew a remarkably similar distinction over a century ago. He split time into two kinds:
Spatialized time (temps) — clock time, which can be sliced, measured, and arranged on a timeline. It’s Newtonian, homogeneous, quantifiable.
Duration (duree) — time as experienced by consciousness, continuous, indivisible, textured. A stretch of anticipatory waiting and a stretch of bored waiting may be identical on the clock, but in duration they’re completely different experiences.
Engineering “latency optimization” is essentially about manipulating Bergsonian time textures. You may not be able to make the response come back faster, but you can change the user’s experience of waiting:
- Progress feedback transforms unpredictable waiting into predictable — anxiety drops, duration shrinks
- Cancel mechanisms transform passive waiting into active choice — sense of control rises, duration shrinks
- Background processing transforms blocking waits into non-blocking — freedom increases, duration nearly vanishes
When you’re doing UX optimization, you’re really doing philosophy of time.
Three: The Arrow of Time — Why Undo Is So Hard in Reality
You can git checkout <commit> to restore a past state. You can Ctrl+Z to undo the last step. You can restore an entire database from a backup.
But you can’t make a shattered coffee mug reassemble itself. You can’t take back words once spoken. You can’t bring back someone who’s gone.
Why is “time travel” so easy in the software world but so impossible in reality?
The answer lies in a physics concept: entropy — the measure of a system’s disorder. The second law of thermodynamics says that the entropy of a closed system can only increase or stay the same, never decrease. This is the physical foundation of the arrow of time — time has a direction because the universe tends toward greater disorder.
And git‘s ability to “go back in time” works because it isn’t actually reversing time. Its mechanism rests on three prerequisites:
Complete records — every commit saves a full snapshot. You’re not returning to the past; you’re reloading a saved record of the past. But reality doesn’t save a complete snapshot of every instant.
Isolatable side effects — git checkout only changes your working directory; it doesn’t affect other people’s branches or the remote server’s state. But in reality, every action has butterfly-effect-like side effects.
Discrete states — code is text files; state is discrete bits. They can be exactly copied and exactly compared. But reality is continuous, and at the quantum level, the uncertainty principle prevents you from fully recording any system.
Augustine wrote in his Confessions: “The past no longer exists, the future does not yet exist, and the present constantly slips away.” Engineers can “save” the past because they’ve converted past states into data that still exists in the present. This isn’t time travel — it’s saving your game.
And real time is irreversible. This irreversibility isn’t a technical limitation. It’s a fundamental feature of the universe.
Modern Connections: The Time Crisis of the AI Era
The Attention Economy: Who’s Scheduling Your Time?
In the age of smartphones and push notifications, your time no longer fully belongs to you.
Every notification is a context switch. Research shows it takes an average of 23 minutes to return to a state of deep focus after a single interruption. If you’re interrupted three times an hour, you effectively never enter real deep work.
Engineering has a precise analogy for this: thrashing — when an operating system runs low on memory and constantly swaps pages between disk and RAM, almost all of its time goes to swapping rather than actual computation. CPU utilization looks like 100%, but real output approaches zero.
You’ve probably experienced the human version of thrashing: a whole day spent feeling busy and exhausted, only to realize at night that nothing was actually accomplished. Your time was sliced into countless fragments, each too short to hold any thought of depth.
Social media platforms exacerbate this by design. Their core metric is “time on platform” — but they’re not optimizing for time that feels fulfilling to you. They’re optimizing for time that you’re occupied. In Bergson’s framework, they’re stealing your duration and leaving you with only fragmented, hollow clock time.
The AI Accelerator: When Everything Can Be Compressed
Generative AI is compressing the time required for nearly all knowledge work. Writing a report used to take a day; now it might take ten minutes. Learning a new framework used to take a week; now you might be productive by afternoon.
But this raises a philosophical question: where does the compressed time go?
If you use AI to compress four hours of work into thirty minutes, what do you do with the remaining three and a half hours? More work — until your entire day becomes a series of thirty-minute sprints?
Or can the saved time be invested in things that can’t be compressed — thinking, daydreaming, walking, deep conversation with another person?
Martin Heidegger warned that the essence of technology is not the tool itself but a “framework” (Gestell) that makes us see everything as a resource to be exploited. When we treat time as a compressible resource, we may be losing the most valuable part of time — the duration that doesn’t pursue efficiency and can’t be quantified.
The Tyranny of Immediacy
Modern software systems worship “real-time” — instant messaging, instant push notifications, instant updates. Latency is treated as a defect. Waiting is treated as failure.
But the philosophy of time reminds us: not everything valuable should be instantaneous.
Brewing takes time. Grief takes time. Understanding takes time. Relationships take time.
When we apply software’s “real-time” mindset to life — expecting all problems to be solved instantly, all emotions to be processed instantly, all growth to happen instantly — we’re using the wrong time model to understand human existence.
Reflections & Takeaways: A Programmer’s Time Literacy
Are You Managing Time, or Attention?
Most time management methods are really attention management. The Pomodoro Technique doesn’t manage time — the 25 minutes of physical time don’t change because you used a tomato timer — it manages how you allocate attention.
If time is, as Aristotle said, “the measure of change,” then what truly matters isn’t how much time you have but how much meaningful change you produce within it.
One hour of flow state can generate more change than an entire day of fragmented work. The value of time isn’t in its length but in its density.
Time Isn’t Something You “Have”
We habitually say “I have time” or “I don’t have time,” as if time were a resource you can hold. But a more precise statement might be: you don’t exist “in” time — you are time.
Heidegger’s concept of Dasein points out that human existence is fundamentally temporal. You’re not a fixed entity moving through time; you’re an unfolding process. Your past constitutes your memories and habits, your future constitutes your plans and anxieties, and your present is the instant where the two converge.
For programmers, this means: you’re not “spending time” writing code. Through the act of writing code, you’re becoming a particular version of yourself. Every debugging session, every refactor, every new technology learned updates the state of the “system” that is you.
Four Time Mental Models to Take With You
-
Distinguish the three layers of time — Algorithmic time governs scale, wall-clock time governs experience, subjective time governs meaning. When optimizing, be clear about which layer you’re optimizing.
-
Respect irreversibility — The arrow of time points one way. Rather than fantasizing about going back, build good “save mechanisms”: version control, journaling, regular reflection.
-
Protect contiguous time — Guard your attention the way you guard memory. Reduce context switches; maintain flow state. Fragmented time has almost no deep value.
-
Accept incompressibility — Some things need time to unfold slowly. Growth, trust, understanding — these don’t support a “speed up” option.
Conclusion
Back to that 3 AM deployment.
Four minutes of wall-clock time. Billions of CPU clock cycles. And a stretch of subjective experience that anxiety inflated into something approaching eternity.
Three kinds of time, happening simultaneously, each one real.
As a programmer, you possess a distinctive time literacy — you know how to analyze latency, how to optimize performance, how to manage waiting in an asynchronous world.
But perhaps the most important kind of literacy is this: knowing when to stop optimizing.
Not all time needs to be compressed, filled, or maximally utilized.
Sometimes the best use of time is to let it flow through you.
No rush. No deadline. No optimization.
Like a side project with no due date, existing purely out of curiosity.
That kind of time is the only kind that truly belongs to you.
Next Article Preview
Pointers & Memory: The Continuity of Personal Identity
You’ve moved, changed jobs, overhauled your values. Are you still “you”?
- If you were perfectly copied — two identical “yous” — which one is the original?
- How does the difference between shallow copy and deep copy map to the philosophical debate over body and soul?
- Is forgetting a bug or a feature? How does garbage collection maintain a person’s “runnability”?
- When AI can simulate your voice and memories, where are the boundaries of “you”?
Next time, we’ll use pointers, references, and memory management to disassemble the most tangled philosophical question of the last two millennia: personal identity.
References
- Aristotle. Physics, Book IV. (Time as the measure of change)
- Augustine. Confessions, Book XI. (The classic meditation on the subjectivity of time)
- Bergson, Henri. Time and Free Will. George Allen & Unwin, 1910. (Duration vs. spatialized time)
- Heidegger, Martin. Being and Time. SCM Press, 1962. (The temporality of Dasein)
- Newton, Isaac. Philosophiae Naturalis Principia Mathematica, 1687. (Absolute time)
- Leibniz, G.W. & Clarke, Samuel. The Leibniz-Clarke Correspondence, 1715-1716. (Relational time)
- Cormen, Thomas H., et al. Introduction to Algorithms. MIT Press, 2009. (Big-O and time complexity)
- Mark, Gloria, et al. “The Cost of Interrupted Work.” Proceeding of CHI, 2008. (Research on attention switching)
