||This article has multiple issues. Please help improve it or discuss these issues on the talk page.
In computer science, algorithmic efficiency is used to describe those properties of an algorithm which relate to the amount of resources used by the algorithm. An algorithm must be analysed to determine its resource usage. Algorithmic efficiency can be thought of as analogous to engineering productivity for a repeating or continuous process.
Gal-Ezer and Zur have stated: "The design of efficient algorithms to solve algorithmic problems is one of the most important research fields in computer science. Good algorithm design is crucial to the performance of all software systems and therefore essential in every computer science program of study."
For maximum efficiency we wish to minimize resource usage. However, the various resources (e.g. time, space) can not be compared directly, so which of two algorithms is considered to be more efficient often depends on which measure of efficiency is being considered as the most important, e.g. is the requirement for high speed, or for minimum memory usage, or for some other measure?
- Note that this article is not about optimization, which is discussed in program optimization, optimizing compiler, loop optimization, and object code optimizer. The term 'optimization' is itself misleading, since all that can generally be done is an 'improvement'.
"In almost every computation a great variety of arrangements for the succession of the processes is possible, and various considerations must influence the selections amongst them for the purposes of a calculating engine. One essential object is to choose that arrangement which shall tend to reduce to a minimum the time necessary for completing the calculation"
Early electronic computers were severely limited both by the speed of operations and the amount of memory available. In some cases it was realised that there was a space–time tradeoff, whereby a task could be handled either by using a fast algorithm which used quite a lot of working memory, or by using a slower algorithm which used very little working memory. The engineering tradeoff was then to use the fastest algorithm which would fit in the available memory.
Modern computers are very much faster than the early computers, and have a much larger amount of memory available (Gigabytes instead of Kilobytes). Nevertheless, Donald Knuth emphasised that efficiency is still an important consideration:
"In established engineering disciplines a 12% improvement, easily obtained, is never considered marginal and I believe the same viewpoint should prevail in software engineering"
An algorithm is considered efficient if its resource consumption is at or below some acceptable level. Roughly speaking, 'acceptable' means: will it run in a reasonable amount of time on an available computer. Since the 1950s computers have seen dramatic increases in both the available computational power and in the available amount of memory, so current acceptable levels would have been unacceptable even 10 years ago.
Computer manufacturers frequently bring out new models, often with higher performance. Software costs can be quite high, so in some cases the simplest and cheapest way of getting higher performance might be to just buy a faster computer, provided it is compatible with an existing computer.
There are many ways in which the resources used by an algorithm can be measured: the two most common measures are speed and memory usage; other measures could include transmission speed, temporary disk usage, long-term disk usage, power consumption, total cost of ownership, response time to external stimuli, etc. Many of these measures depend on the size of the input to the algorithm (i.e. the amount of data to be processed); they might also depend on the way in which the data is arranged (e.g. some sorting algorithms perform poorly on data which is already sorted, or which is sorted in reverse order).
In practice, there are other factors which can affect the efficiency of an algorithm, such as requirements for accuracy and/or reliability. As detailed below, the way in which an algorithm is implemented can also have a significant effect on actual efficiency, though many aspects of this relate to optimisation issues.
In the theoretical analysis of algorithms, the normal practice is to estimate their complexity in the asymptotic sense, i.e. use Big O notation to represent the complexity of an algorithm as a function of the size of the input n. This is generally sufficiently accurate when n is large, but may be misleading for small values of n (e.g. bubble sort may be faster than quicksort when only a few items are to be sorted).
Some examples of Big O notation include:
|constant||Determining if a number is even or odd; Using a constant-size lookup table; Using a suitable hash function for looking up an item.|
|logarithmic||Finding an item in a sorted array with a binary search or a balanced search tree as well as all operations in a Binomial heap.|
|linear||Finding an item in an unsorted list or a malformed tree (worst case) or in an unsorted array; Adding two n-bit integers by ripple carry.|
|linearithmic, loglinear, or quasilinear||Performing a Fast Fourier transform; heapsort, quicksort (best and average case), or merge sort|
|quadratic||Multiplying two n-digit numbers by a simple algorithm; bubble sort (worst case or naive implementation), Shell sort, quicksort (worst case), selection sort or insertion sort|
|exponential||Finding the (exact) solution to the travelling salesman problem using dynamic programming; determining if two logical statements are equivalent using brute-force search|
Benchmarking: measuring performance
For new versions of software or to provide comparisons with competitive systems, benchmarks are sometimes used, which assist with gauging an algorithms relative performance. If a new sort algorithm is produced for example it can be compared with its predecessors to ensure that at least it is efficient as before with known data—taking into consideration any functional improvements. Benchmarks can be used by customers when comparing various products from alternative suppliers to estimate which product will best suit their specific requirements in terms of functionality and performance. For example in the mainframe world certain proprietary sort products from independent software companies such as Syncsort compete with products from the major suppliers such as IBM for speed.
Some benchmarks provide opportunities for producing an analysis comparing the relative speed of various compiled and interpreted languages for example and The Computer Language Benchmarks Game compares the performance of implementations of typical programming problems in several programming languages.
(Even creating "do it yourself" benchmarks to get at least some appreciation of the relative performance of different programming languages, using a variety of user specified criteria, is quite simple to produce as this "Nine language Performance roundup" by Christopher W. Cowell-Shah demonstrates by example)
Implementation issues can also have an effect on actual efficiency, such as the choice of programming language, or the way in which the algorithm is actually coded, or the choice of a compiler for a particular language, or the compilation options used, or even the operating system being used. In some cases a language implemented by an interpreter may be much slower than a language implemented by a compiler.
There are other factors which may affect time or space issues, but which may be outside of a programmer's control; these include data alignment, data granuality, garbage collection, instruction-level parallelism, and subroutine calls. 
Some processors have capabilities for vector processing, which allow a single instruction to operate on multiple operands; it may or may not be easy for a programmer or compiler to use these capabilities. Algorithms designed for sequential processing may need to be completely redesigned to make use of parallel processing.
Another problem which can arise with compatible processors is that they may implement an instruction in different ways, so that instructions which are relatively fast on some models may be relatively slow on other models; this can make life difficult for an optimizing compiler.
Measures of resource usage
Measures are normally expressed as a function of the size of the input n.
The two most common measures are:
- Time: how long does the algorithm take to complete.
- Space: how much working memory (typically RAM) is needed by the algorithm. This has two aspects: the amount of memory needed by the code, and the amount of memory needed for the data on which the code operates.
- Direct power consumption: power needed directly to operate the computer.
- Indirect power consumption: power needed for cooling, lighting, etc.
In some cases other less common measures may also be relevant:
- Transmission size: bandwidth could be a limiting factor. Data compression can be used to reduce the amount of data to be transmitted. Displaying a picture or image (e.g. Google logo) can result in transmitting tens of thousands of bytes (48K in this case) compared with transmitting six bytes for the text "Google".
- External space: space needed on a disk or other external memory device; this could be for temporary storage while the algorithm is being carried out, or it could be long-term storage needed to be carried forward for future reference.
- Response time: this is particularly relevant in a real-time application when the computer system must respond quickly to some external event.
- Total cost of ownership: particularly if a computer is dedicated to one particular algorithm.
Analyse the algorithm, typically using time complexity analysis to get an estimate of the running time as a function as the size of the input data. The result is normally expressed using Big O notation. This is useful for comparing algorithms, especially when a large amount of data is to processed. More detailed estimates are needed for algorithm comparison when the amount of data is small (though in this situation time is less likely to be a problem anyway). Algorithms which include parallel processing may be more difficult to analyse.
Time the use of an algorithm. Many programming languages have an available function which provides CPU time usage. For long-running algorithms the elapsed time could also be of interest. Results should generally be averaged over several tests.
This sort of test also depends heavily on the selection of a particular programming language, compiler, and compiler options, so algorithms being compared must all be implemented under the same conditions.
This section is concerned with the use of main memory (often RAM) while the algorithm is being carried out. As for time analysis above, analyse the algorithm, typically using space complexity analysis to get an estimate of the run-time memory needed as a function as the size of the input data. The result is normally expressed using Big O notation.
There are up to four aspects of memory usage to consider:
- The amount of memory needed to hold the code for the algorithm.
- The amount of memory needed for the input data.
- The amount of memory needed for any output data (some algorithms, such as sorting, often just rearrange the input data and don't need any space for output data).
- The amount of memory needed as working space during the calculation (this includes both named variables and any stack space needed by routines called during the calculation; this stack space can be significant for algorithms which use recursive techniques).
Early electronic computers, and early home computers, had relatively small amounts of working memory. E.g. the 1949 EDSAC had a maximum working memory of 1024 17-bit words, while the 1980 Sinclair ZX80 came initially with 1024 8-bit bytes of working memory.
Current computers can have relatively large amounts of memory (possibly Gigabytes), so having to squeeze an algorithm into a confined amount of memory is much less of a problem than it used to be. But the presence of three different categories of memory can be significant:
- Cache memory (often static RAM) - this operates at speeds comparable with the CPU.
- Main physical memory (often dynamic RAM) - this operates somewhat slower than the CPU.
- Virtual memory (often on disk) - this gives the illusion of lots of memory, and operates thousands of times slower than RAM.
An algorithm whose memory needs will fit in cache memory will be much faster than an algorithm which fits in main memory, which in turn will be very much faster than an algorithm which has to resort to virtual memory. To further complicate the issue, some systems have up to three levels of cache memory, with varying effective speeds. Different systems will have different amounts of these various types of memory, so the effect of algorithm memory needs can vary greatly from one system to another.
In the early days of electronic computing, if an algorithm and its data wouldn't fit in main memory then the algorithm couldn't be used. Nowadays the use of virtual memory appears to provide lots of memory, but at the cost of performance. If an algorithm and its data will fit in cache memory, then very high speed can be obtained; in this case minimising space will also help minimise time. An algorithm which will not fit completely in cache memory but which exhibits locality of reference may perform reasonably well.
Examples of efficient algorithms
- quicksort First known sorting algorithm with speed of order .
- heapsort Another fast sorting algorithm.
- binary search Searching an ordered table.
- Boyer–Moore string search algorithm Finding a string within another string.
The word optimize is normally used in relation to an existing algorithm/computer program (i.e. to improve upon completed code). In this section it is used both in the context of existing programs and also in the design and implementation of new algorithms, thereby avoiding the most common performance pitfalls. It is clearly wasteful to produce a working program—at first using an algorithm that ignores all efficiency issues—only to then have to redesign or rewrite sections of it if found to offer poor performance. Optimization can be broadly categorized into two domains:-
- Environment specific—that are essentially worthwhile only on certain platforms or particular computer languages
- General techniques—that apply irrespective of platform
Software validation versus hardware validation
An optimization technique that was frequently taken advantage of on 'legacy' platforms was that of allowing the hardware (or microcode) to perform validation on numeric data fields such as those coded in (or converted to) packed decimal (or packed BCD). The choice was to either spend processing time checking each field for a valid numeric content in the particular internal representation chosen or simply assume the data was correct and let the hardware detect the error upon execution. The choice was highly significant because to check for validity on multiple fields (for sometimes many millions of input records), it could occupy valuable computer resources. Since input data fields were in any case frequently built from the output of earlier computer processing, the actual probability of a field containing invalid data was exceedingly low and usually the result of some 'corruption'. The solution was to incorporate an 'event handler' for the hardware detected condition ('data exception)' that would intercept the occasional errant data field and either 'report, correct and continue' or, more usually, abort the run with a core dump to try to determine the reason for the bad data.
Similar event handlers are frequently utilized in today's web based applications to handle other exceptional conditions but repeatedly parsing data input, to ensure its validity before execution, has nevertheless become much more commonplace—partly because processors have become faster (and the perceived need for efficiency in this area less significant) but, predominantly—because data structures have become less 'formalized' (e.g. .csv and .tsv files) or uniquely identifiable (e.g. packed decimal). The potential savings using this type of technique may have therefore fallen into general dis-use as a consequence and therefore repeated data validations and repeated data conversions have become an accepted overhead. Ironically, one consequence of this move to less formalized data structures is that a corruption of say, a numeric binary integer value, will not be detected at all by the hardware upon execution (for instance: is an ASCII hexadecimal value '20202020' a valid signed or unsigned binary value—or simply a string of blanks that has corrupted it?)
Readability, trade offs and trends
One must be careful, in the pursuit of good coding style, not to over-emphasize efficiency. Frequently, a clean, readable and 'usable' design is much more important than a fast, efficient design that is hard to understand. There are exceptions to this 'rule' (such as embedded systems, where space is tight, and processing power minimal) but these are rarer than one might expect.
However, increasingly, for many 'time critical' applications such as air line reservation systems, point-of-sale applications, ATMs (cash-point machines), Airline Guidance systems, Collision avoidance systems and numerous modern web based applications—operating in a real-time environment where speed of response is fundamental—there is little alternative.
Implications for algorithmic efficiency
A recent report, published in December 2007, from Global Action Plan, a UK-based environmental organisation found that computer servers are "at least as great a threat to the climate as SUVs or the global aviation industry" drawing attention to the carbon footprint of the IT industry in the UK. According to an Environmental Research Letters report published in September 2008, "Total power used by information technology equipment in data centers represented about 0.5% of world electricity consumption in 2005. When cooling and auxiliary infrastructure are included, that figure is about 1%. The total data center power demand in 2005 is equivalent (in capacity terms) to about seventeen 1000 MW power plants for the world."
Some media reports claim that performing two Google searches from a desktop computer can generate about the same amount of carbon dioxide as boiling a kettle for a cup of tea, according to new research; however, the factual accuracy of this comparison is disputed, and the author of the study in question asserts that the two-searches-tea-kettle statistic is a misreading of his work.
Greentouch, a recently established consortium of leading Information and Communications Technology (ICT) industry, academic and non-governmental research experts, has set itself the mission of reducing reduce energy consumption per user by a factor of 1000 from current levels. "A thousand-fold reduction is roughly equivalent to being able to power the world’s communications networks, including the Internet, for three years using the same amount of energy that it currently takes to run them for a single day". The first meeting in February 2010 will establish the organization’s five-year plan, first year deliverables and member roles and responsibilities. Intellectual property issues will be addressed and defined in the forum’s initial planning meetings. The conditions for research and the results of that research will be high priority for discussion in the initial phase of the research forum’s development.
Computers having become increasingly more powerful over the past few decades, emphasis was on a 'brute force' mentality. This may have to be reconsidered in the light of these reports and more effort placed in future on reducing carbon footprints through optimization. It is a timely reminder that algorithmic efficiency is just another aspect of the more general thermodynamic efficiency. The genuine economic benefits of an optimized algorithm are, in any case, that more processing can be done for the same cost or that useful results can be shown in a more timely manner and ultimately, acted upon sooner.
Criticism of the current state of programming
- David May FRS a British computer scientist and currently Professor of Computer Science at University of Bristol and founder and CTO of XMOS Semiconductor, believes one of the problems is that there is a reliance on Moore's law to solve inefficiencies. He has advanced an 'alternative' to Moore's law (May's law) stated as follows:
Software efficiency halves every 18 months, compensating Moore's Law
In ubiquitous systems, halving the instructions executed can double the battery life and big data sets bring big opportunities for better software and algorithms: Reducing the number of operations from N x N to N x log(N) has a dramatic effect when N is large... for N = 30 billion, this change is as good as 50 years of technology improvements
- Software author Adam N. Rosenburg in his blog "The failure of the Digital computer", has described the current state of programming as nearing the "Software event horizon", (alluding to the fictitious "shoe event horizon" described by Douglas Adams in his Hitchhiker's Guide to the Galaxy book). He estimates there has been a 70 dB factor loss of productivity or "99.99999 percent, of its ability to deliver the goods", since the 1980s—"When Arthur C. Clarke compared the reality of computing in 2001 to the computer HAL in his book 2001: A Space Odyssey, he pointed out how wonderfully small and powerful computers were but how disappointing computer programming had become".
- Conrad Weisert gives examples, some of which were published in ACM SIGPLAN (Special Interest Group on Programming Languages) Notices, December 1995 in: "Atrocious Programming Thrives"
- Marc Andreessen co-founder of Netscape is quoted in "Mavericks at Work" (ISBN 0060779616) as saying "Five great programmers can completely outperform 1,000 mediocre programmers."
Competitions for the best algorithms
The following competitions invite entries for the best algorithms based on some arbitrary criteria decided by the judges:-
- Analysis of algorithms - how to determine the resources needed by an algorithm
- Arithmetic coding—a form of variable-length entropy encoding for efficient data compression
- Associative array—a data structure that can be made more efficient using Patricia trees or Judy arrays
- Binary search algorithm—a simple and efficient technique for searching sorted arrays
- Benchmark—a method for measuring comparative execution times in defined cases
- Best, worst and average case—considerations for estimating execution times in three scenarios
- Branch table—a technique for reducing instruction path-length, size of machine code, (and often also memory)
- Comparison of programming paradigms—paradigm specific performance considerations
- Compiler optimization—compiler-derived optimization
- Computational complexity theory
- Computer performance—computer hardware metrics
- Data compression—reducing transmission bandwidth and disk storage
- Database index—a data structure that improves the speed of data retrieval operations on a database table
- Entropy encoding—encoding data efficiently using frequency of occurrence of strings as a criterion for substitution
- Garbage collection—automatic freeing of memory after use
- Green computing—a move to implement 'greener' technologies, consuming less resources
- Huffman algorithm—an algorithm for efficient data encoding
- Locality of reference—for avoidance of caching delays caused by non-local memory access
- Loop optimization
- Memory management
- Optimization (computer science)
- Performance analysis—methods of measuring actual performance of an algorithm at run-time
- Real-time computing—further examples of time-critical applications
- Run-time analysis—estimation of expected run-times and an algorithm's scalability
- Simultaneous multithreading
- Speculative execution or Eager execution
- Threaded code—similar to virtual method table or branch table
- Virtual method table—branch table with dynamically assigned pointers for dispatching
- Improving Managed code Performance—Microsoft MSDN Library
- Gal-Ezer, Judith; Zur, Ela (2003), "The efficiency of algorithms—misconceptions", Computers and Education (Elsevier) 42 (3): 215–226, retrieved 17 May 2013
- Green, Christopher, Classics in the History or Psychology, retrieved 19 May 2013
- Knuth, Donald (1974), "Structured Programming with go-to Statements", Computing Surveys (ACM) 6 (4), retrieved 19 May 2013
- "Floating Point Benchmark: Comparing Languages (Fourmilog: None Dare Call It Reason)". Fourmilab.ch. 2005-08-04. Retrieved 2011-12-14.
- "Whetstone Benchmark History". Roylongbottom.org.uk. Retrieved 2011-12-14.
- "The Computer Language Benchmarks Game". benchmarksgame.alioth.debian.org. Retrieved 2011-12-14.
- Guy Lewis Steele, Jr. "Debunking the 'Expensive Procedure Call' Myth, or, Procedure Call Implementations Considered Harmful, or, Lambda: The Ultimate GOTO". MIT AI Lab. AI Lab Memo AIM-443. October 1977.
- "Environmental Charity". Global Action Plan. Retrieved 2011-12-14.
- "Computer servers 'as bad' for climate as SUVs - environment - 03 December 2007 - New Scientist". Environment.newscientist.com. Retrieved 2011-12-14.
- "Innovators: Efficiency Matters - March April 2007 - Sierra Magazine". Sierra Club. Retrieved 2011-12-14.
- "Worldwide electricity used in data centers". Iop.org. Retrieved 2011-12-14.
- "Research Reveals Environmental Impact of Google Searches". Fox News. 2009-01-12.
- Timmer, John (2009-01-12). "Analysis: environmental impact of Googling hard to quantify". Arstechnica.com. Retrieved 2011-12-14.
- "Technology News: Green Tech: Harvard Physicist Sets Record Straight on Internet Carbon Study". Technewsworld.com. Retrieved 2011-12-14.
- "About Us". Green Touch. Retrieved 2011-12-14.
- "Gee Rittenhouse, Bell Labs, on Shannon's Law and the Green Touch initiative". YouTube. 2010-01-11. Retrieved 2011-12-14.
- "Challenges and Opportunities". Green Touch. Retrieved 2011-12-14.
- "Energy Efficiency in the Data Center". YouTube. 2008-07-22. Retrieved 2011-12-14.
- "Atrocious Programming Thrives". Idinews.com. 2003-01-09. Retrieved 2011-12-14.
- Fagone, Jason (2010-11-29). "Teen Mathletes Do Battle at Algorithm Olympics". Wired.
|Wikibooks has a book on the topic of: Optimizing Code for Speed|
- Animation of the Boyer-Moore algorithm (Java Applet)
- Programming Optimization by Paul Hsieh
- also see more external links in related article "program optimization"
- "Why learning assembler is still a good idea" By Randall Hyde
- Writing efficient programs ("Bentley's Rules") by Jon Bentley
- "Why software still stinks" an article by Scott Rosenberg
- "In Defense of Efficient Computing" an article by Rod Furlan
- "Performance Anti-Patterns" by Bart Smaalders
- "How algorithms shape our world". A TED (conference) Talk by Kevin Slavin.