Does evolution conserve software code like it does genes?

mskar1 pts0 comments

Does evolution conserve software code in a similar way to genes?

Little Leaps

SubscribeSign in

Does evolution conserve software code in a similar way to genes?<br>Utility-functions in our software and biology

Michael Skarlinski<br>May 31, 2026

Share

A common analogy of a DNA sequence is that it’s the “code” for a biological system. This code is under constant mutation pressure, an accumulated history of random mutation events change the sequence over time. When random mutations lead to deleterious outcomes, cells are less likely to survive and propagate the change into the future. Therefore, a section of DNA which remains unchanged or conserved for a long period of time is more likely to have an important function.<br>I was interested in whether or not this analogy would hold in a real software codebase. If I looked the accumulated history of changes, would the conserved parts be the most important? In a software codebase git allows us to see a history of changes (or mutations), and we can search for analogous functions which are preserved overtime. I wrote some code to do that here.<br>If we utilize this history to find the most “evolutionarily preserved code”, what does it look like in open source software? Turns out it looks like a utility function. ~ 60% of the top ranked “conserved” functions are utility functions which have a re-usable general purpose across the codebase, but are not directly aligned with the library’s goal.<br>What about in our cells? It’s basically the same! 56%-65% of the top 1000 most conserved genes are “housekeeping” or utility genes expressed across all cells, independent of function. In both the biological case and the software case these utility-esque functions/genes over-index relative to the baseline rate in the genome/codebases as a whole, so there is a real correlation between being conserved and being a utility function.<br>It’s unclear if this represents a broader complexity trend, but it’s pretty wild that the most conserved “code” in software and biology have an analogous purpose.<br>How to find evolutionary conserved code

(you can skip this section if you just want to see the results, they are understandable without it)<br>This biological analogy isn’t perfect, so I had to make some simplifying assumptions. Firstly, changes to a codebase aren’t really random, they are biased towards new features or bug-fixes, and usually recorded in coherent units (commits). I considered each individual commit to a codebase as a single mutation “trial”. Commits are tracked via each individual line changed, so, as a simplifying assumption, I only considered a “function” as the smallest unit that we would analyze. In each recorded commit, I kept a database of whether a function materially changed or not. (I tried to skip trivial things like renames or docstring updates)<br>We can make a pretty simple metric for evolutionary conservation of each recorded function, the ratio of un-altering commits to total commits, or trials. I would like to model the uncertainty of this ratio, because a function which has survived without changes in 100 commits is much more stable than one which has survived unchanged after 2 commits. So I modeled each trial for function f as a Bernoulli event with unknown survival probability p. Using a Beta conjugate prior over p as a function of k (unchanged outcomes) in n (total trials) gives us a posterior distribution like this:<br>\(\text{Survival Posterior:} \quad p \mid k, n \sim \mathrm{Beta}(\alpha + k,\; \beta + n - k)\)

where,<br>α, β are Beta prior parameters (default 1, 1; uniform)

n is the total trials/commits for a function f

k is the total trials/commits where f survived unchanged

To properly rank the posterior distribution, I used the lower credible bound (p=0.05), which captures uncertainty as a single number. So that brings us to our evolutionary quality metric (EQM).<br>\(\text{EQM}(f) = \mathrm{LCB}_p\!\left[\mathrm{Beta}(\alpha + k,\; \beta + n - k)\right]\)

Awesome — but, commits are often isolated to a single feature, so we can’t really consider each commit as contributing to a trial (n) for every single function f. I needed some logic to determine when a commit “counted” as an attempted mutation. My approach here was to use the AST parsed call graph of each function to determine if either the function itself was altered or if any caller function was altered. I only traversed a single node in this call graph. The logic is that if a developer modified or added a calling function, this would be the circumstance that would create the most mutation pressure.<br>Now with this metric, we can rank every function in large open source codebases to look at the most “conserved” functions. (see code here )<br>Conserved Code Examples

What does code look like when we examine the top ranked conserved functions? Let’s check out some popular open source projects.<br>Let’s start with FastAPI, where the top ranked most preserved function is a very simple utility function,...

function code conserved software commits like

Related Articles