Skip to main content

Benchmarking recursion in different languages

·7 mins

I used the Fibonacci sequence to test the speed of recursive calls in different languages. Take the results with a grain of salt because my computer is not a controlled environment. I found that Python was slower than I expected, while JavaScript was faster than I expected. Bash was more than 100,000 times slower than C because the Bash benchmark did not finish after the 5-hour mark. My hypothesis is that Bash is very slow because math is done in sub-shells, requiring bash to spawn a process for every arithmetic operation.

Execution times for calculating the 39th term of the Fibonacci sequence:

LanguageCompiler/InterpreterFlagsTime (sec)
Cgcc 12.3.0-O3 -Ofast0.124
C++g++ 12.3.0-O3 -Ofast0.125
Rustrustc 1.73.0-C opt-level=30.247
Javajavac/java 17.0.7None0.460
Dartdart 3.3.4compile aot-snapshot0.466
JavaScriptnode 21.2.0None0.802
Lualua 5.2.4None8.192
Pythonpython3 3.11.6None10.828
Perlperl 5.38.2None38.966
Vimscriptnvim 0.10.0None346.000
Nushellnu 0.93.0None710.000
BashbashNone18000.000

Implementations #

C
/**
 * @file
 * @brief Calculate the a Fibonacci sequence number from user input.
 */
#include <stdio.h>
#include <stdlib.h>

/**
 * @brief Calculate a Fibonacci sequence number.
 *
 * @param term The sequence number to produce. Don't use large
 * numbers as the time complexity is exponential.
 * @return The sequence number.
 */
int fibonacci(int term) {
    // Base case.
    if (term <= 1) {
        return term;
    }
    // Recursive step.
    return fibonacci(term - 1) + fibonacci(term - 2);
}

/**
 * @brief Calculate a Fibonacci sequence number from user input.
 *
 * @param argc The argument count.
 * @param argv The argument vector.
 * @return The error code.
 */
int main(int argc, char **argv) {
    if (argc > 1) {
        int term = atoi(argv[1]);
        int result = fibonacci(term);
        printf("%d\n", result);
    }
    return 0;
}
C++
/**
 * @file
 * @brief Calculate a Fibonacci sequence number from user input.
 */
#include <iostream>

/**
 * @brief Calculate a Fibonacci sequence number.
 *
 * @param term The sequence number to produce. Don't use large
 * numbers as the time complexity is exponential.
 * @return The sequence number.
 */
int fibonacci(int term) {
  // Base case.
  if (term <= 1) {
    return term;
  }
  // Recursive step.
  return fibonacci(term - 1) + fibonacci(term - 2);
}

/**
 * @brief Calculate a Fibonacci sequence number from user input.
 *
 * @param argc The argument count.
 * @param argv The argument vector.
 * @return The error code.
 */
int main(int argc, char **argv) {
  if (argc > 1) {
    int term = std::stoi(argv[1]);
    int result = fibonacci(term);
    std::cout << result << std::endl;
  }
  return 0;
}
Rust
//! Calculate a Fibonacci sequence number from user input.
use std::env::args;

/// Calculate a Fibonacci sequence number.
///
/// * `term`: The sequence number to produce. Don't use large numbers as the
/// time complexity is exponential.
fn fibonacci(term: i32) -> i32 {
    // Base case.
    if term <= 1 {
        return term;
    }
    // Recursive step.
    fibonacci(term - 1) + fibonacci(term - 2)
}

/// Calculate a Fibonacci sequence number from user input.
fn main() {
    let arguments: Vec<String> = args().collect();
    if let Some(argument) = arguments.get(1) {
        let term: i32 = argument.parse().unwrap_or(0);
        let result = fibonacci(term);
        println!("{}", result);
    }
}
Java
/** Calculate a Fibonacci sequence number from user input. */
class Fibonacci {
  /**
   * Calculate a Fibonacci sequence number.
   *
   * @param term The sequence number to produce. Don't use large numbers as the time complexity is
   *     exponential.
   * @return The sequence number.
   */
  public static int fibonacci(int term) {
    // Base case.
    if (term <= 1) {
      return term;
    }
    // Recursive step.
    return fibonacci(term - 1) + fibonacci(term - 2);
  }

  /**
   * Calculate a Fibonacci sequence number from user input.
   *
   * @param args The command-line arguments.
   */
  public static void main(String[] args) {
    if (args.length > 0) {
      int term = Integer.parseInt(args[0]);
      int result = fibonacci(term);
      System.out.println(result);
    }
  }
}
Dart
/// Calculate a Fibonacci sequence number from user input.
void main(List<String> args) {
    final term = int.parse(args[0]);
    print(fibonacci(term));
}

/// Calculate the Fibonacci sequence number for the [n]-th term.
///
/// Don't use large numbers as the time complexity is exponential.
int fibonacci(int n) {
  // Base case: the first two numbers in the sequence are 0 and 1.
  if (n <= 1) {
    return n;
  }

  // Recursive step: The nth number in the sequence is the sum of the (n - 1)th
  // and (n - 2)th numbers.
  return fibonacci(n - 1) + fibonacci(n - 2);
}
JavaScript
#!/usr/bin/env node

/**
 * @module Calculate a Fibonacci sequence number from user input.
 */

/**
 * Calculate a Fibonacci sequence number.
 *
 * @param {number} term The sequence number to produce. Don't use large numbers
 * as the time complexity is exponential.
 * @returns {number} The sequence number.
 */
function fibonacci(term) {
    // Base case.
    if (term <= 1) {
        return term;
    }
    // Recursive step.
    return fibonacci(term - 1) + fibonacci(term - 2);
}

if (process.argv.length > 2) {
    const term = parseInt(process.argv[2]);
    const result = fibonacci(term);
    console.log(result);
}
Lua
#!/usr/bin/env lua
--- @module Calculate a Fibonacci sequence number from user input.

--- Calculate a Fibonacci sequence number.
--- @param term number The sequence number to produce. Don't use large numbers as
--- the time complexity is exponential.
--- @return number
local function fibonacci(term)
    -- Base case.
    if term <= 1 then
        return term;
    end
    -- Recursive step.
    return fibonacci(term - 1) + fibonacci(term - 2);
end

if #arg >= 1 then
    local term = tonumber(arg[1]) or 0;
    local result = fibonacci(term);
    print(result);
end
Python
#!/usr/bin/python3
"""Calculate a Fibonacci sequence number from user input."""
from sys import argv

def fibonacci(term: int) -> int:
    """Calculate a Fibonacci sequence number.

    Args:
        term (int): The sequence number to produce. Don't use large numbers as
        the time complexity is exponential.

    Returns:
        int: The sequence number.
    """
    # Base case.
    if term <= 1:
        return term
    # Recursive step.
    return fibonacci(term - 1) + fibonacci(term - 2)

def main():
    """Calculate a Fibonacci sequence number from user input."""
    if len(argv) >= 2:
        term = int(argv[1])
        result = fibonacci(term)
        print(result)

if __name__ == "__main__":
    main()
Perl
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';

sub fibonacci {
    my $term = shift;
    # Base case.
    if ($term <= 1) {
        return $term;
    }
    # Recursive step.
    return fibonacci($term - 1) + fibonacci($term - 2);
}

sub main {
    if (scalar @ARGV >= 1) {
        my $value = fibonacci(int($ARGV[0]));
        say($value);
    }
}

unless (caller) {
    main();
}

__END__

=head1 DESCRIPTION

Calculate a Fibonacci sequence number from user input.

=cut

=head1 FUNCTIONS

=over

=item fibonacci($term)

Calculate a Fibonacci sequence number.

$term C<int> is the sequence number to produce. Don't use large numbers as the
time complexity is exponential.

Returns C<int>, the sequence number.

=item main

Calculate a Fibonacci sequence number from user input.

=back

=cut
Vimscript
#!/usr/bin/env -S nvim --cmd ":source fibonacci.vim"
function! Fibonacci(n)
    if a:n <= 2
        return 1
    else
        return Fibonacci(a:n - 2) + Fibonacci(a:n - 1)
    endif
endfunction

echom Fibonacci(39)
quit!
Nushell
#!/usr/bin/env nu

# Calculate a Fibonacci sequence number from user input.
def main [ term: int ] {
    print (fibonacci $term);
}

# Calculate a Fibonacci sequence number.
# Returns: int The sequence number.
def fibonacci [
    term: int # The sequence number to produce. Don't use large numbers as the
              # time complexity is exponential.
] {
    if $term <= 1 {
        # Base case.
        return $term;
    }
    # Recursive step.
    (fibonacci ($term - 1)) + (fibonacci ($term - 2))
}
Bash
#!/usr/bin/bash

# Calculate a Fibonacci sequence number from user input.

# Exit on errors and undefined variables.
set -eu

################################################################################
# Calculate a Fibonacci sequence number.
# Arguments:
#     $1: int The sequence number to produce. Don't use large numbers as
#         the time complexity is exponential.
# Outputs:
#     int The sequence number.
################################################################################
fibonacci() {
    declare -ir term=$1
    # Base case.
    if (( term <= 1 )); then
        echo $term
        return
    fi
    # Recursive step.
    echo $(( $(fibonacci $((term - 1)) ) + $(fibonacci $((term - 2)) ) ))
}

fibonacci $1