Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is BASH very slow?

Tags:

bash

I was solving this question on SPOJ - http://www.spoj.com/problems/ALICESIE/

What the question boils down to print (n+1)/2

This is my C code which passes in 0.03s

    #include <stdio.h>
    int main() {
        int test, n;
        scanf("%d", &test);
        while(test--) {
            scanf("%d", &n);
            printf("%d\n", (n + 1) >> 1);
        }
        return 0;
    }

while this is my BASH code which gives Time Limit Exceeded ( i.e. > 1s )

read test
while (( test-- ))
do
    read n
    echo "$(((n+1)/2))"
done 

Can anyone let me know why is this happening ? Is BASH very slow ? Thanks.

like image 791
Rajarshi Sarkar Avatar asked Apr 12 '13 15:04

Rajarshi Sarkar


People also ask

Is Bash script slow?

Shell loops are slow and bash's are the slowest. Shells aren't meant to do heavy work in loops. Shells are meant to launch a few external, optimized processes on batches of data.

Is Bash slower than Python?

Python is drastically faster on text processing, which is a common operation. If I perform the same search 10000 times on each language, on Bash it takes 1m24s, on Python 636ms. This is because Bash use a sub-process for each operation of the text processing, which is slow to create.

Is Bash fast?

Python is faster than Bash and is ranked 1st, while Bash is ranked 34th. The most important reasons people chose Python are that it can be used for almost any task. It works on most major operating systems and is also installed by default on most Unix/Linus systems. It is very similar to writing pseudocode.

How do I make my Bash script run faster?

There are few ways to make your shell (eg Bash) execute faster. Try to use less of external commands if Bash's internals can do the task for you. Eg, excessive use of sed , grep , awk et for string/text manipulation. If you are manipulating relatively BIG files, don't use bash's while read loop.


3 Answers

Bash is slow in executing number-crunching. But that isn't what Bash was designed for.

Bash is very fast in whipping up a script for automating some repetitive action. It's fast to modify a faulty Bash script and run it again. It's fast to find out what exactly a Bash script is doing (as opposed to having to hunt down the source for the C executable you're looking at).

And the list goes on.

C and Bash are two very different breeds of languages and environments. If you complain about Bash being slow, you are using it for the wrong kind of problem.

"Do not complain that the screwdriver sucks at driving a nail into the wall."

like image 112
DevSolar Avatar answered Oct 11 '22 15:10

DevSolar


You're comparing compiled code with a script language (Bash).

Bash scripts will always be slower than compiled code as they need to be interpreted.

As you probably know, in order to run your code written in C you first need to compile it. When it comes to Bash scripts, you don't have to read it, the code is just "read on the fly". So Bash is slower than C.

like image 42
MMM Avatar answered Oct 11 '22 14:10

MMM


Bash is slower than C, for sure, because of the reasons given in other answers, but that doesn't explain what's happening here. I suspect you're letting one of your reads hang forever, until timeout. When I implement this:

#!/bin/bash

main() {
    local test
    local i
    local n
    read test
    for (( i=$test; i>0; i--)); do
        read n
        echo "$(((n+1)/2))"
    done
}

time {
    echo 1000
    printf '%d\n' {1002..2}
} | main

It doesn't take very much time:

real    0m0.033s
user    0m0.029s
sys 0m0.013s

You can force the read statements to time out on their own with the -t flag to read, like this:

main() {
    local test
    local i
    local n
    read -t.3 test
    if [[ -z $test ]]; then
        echo "Failed to read a test value within 300ms."
        return 1
    }
    for (( i=$test; i>0; i--)); do
        read -t.3 n
        if [[ -z $n ]]; then
            echo "Failed to read a value for n within 300ms."
            return 1
        }
        echo "$(((n+1)/2))"
    done
}
like image 20
kojiro Avatar answered Oct 11 '22 15:10

kojiro