Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Footprint of Linux Script in 12 Languages
#1
I need a program that is running in the background and provides a service to PHP website. Since the project is in PHP, was going to just run a CLI php in the background, but someone tells me it's too heavy. So I set to see how heavy the program is in different toolkits.

Tests were done on VMWare Virtual Machine i5-2400S CPU @ 2.50GHz, 512M RAM running Ubuntu 12.04.5 LTS

PHP

Code:
<?php
while(1)
    sleep(1); 
?>

Python

Code:
import time
while 1:
    time.sleep(1)

Perl

Code:
#!/usr/bin/perl
print "Hello from Perl\n";
while(1) {
   sleep(1);
}

Lua

Using Lua 5.1 (not installed in stock distribution: sudo apt-get install lua5.1). Btw. Lua program ignored CTRL-C so kill it by pkill lua

Code:
while 1 do
    os.execute("sleep 1")
end

C

I added some output so it links to standard C library. Without that, both C and C++ program result in the same TRS/DRS/RSS.

Compile C: gcc -s test.c -otest_c

Code:
#include <unistd.h>
#include <stdio.h>
int main() {
    printf("Hello from C");
    while(1)
        sleep(1);
}

C++

I added some output so it links to standard C++ library. Without that, both C and C++ program result in the same TRS/DRS/RSS.

Compile C++: g++ -s test.cpp -otest_cpp

Code:
#include <unistd.h>
#include <iostream>
int main() {
   std::cout << "Hello from C++";
   while(1)
       sleep(1);
}

Free Pascal

Compile fpc -Xs test.pas

Code:
program Test;
uses sysutils;
begin
   writeln ('Hello from Pascal');
   while True do begin Sleep(1000); end;
end.

Almquist Shell

There is two versions on Debian, bash and dash

Code:
#!/bin/sh
while true
do
    sleep 1
done

NodeJS

Code:
setInterval(function() {}, 1000);

Mono C#

Code:
using System;
using System.Threading;

public class test5
{
  public static void Main()
  {
       System.Console.WriteLine("Hello from C#");
       while(true)
           Thread.Sleep(1000);
  }
}

Java

Code:
public class Test {
   public static void main(String[] args) {
       System.out.println("Hello from Java");
       while(true)
           try {
               Thread.sleep(1000);
           } catch(InterruptedException e) {}
   }
}

Results

 PID TTY      STAT   TIME  MAJFL   TRS   DRS   RSS %MEM COMMAND
26542 pts/1    S+     0:00      0  7462 255893 11140  2.2 php test.php
26552 pts/1    S+     0:00      0  2499 29720  5448  1.0 python test.py
26580 pts/1    S+     0:00      0     4 20403  2008  0.4 perl test.perl
26630 pts/1    S+     0:00      1   164 13923  1032  0.2 lua test.lua
26758 pts/1    S+     0:00      0     1  4154   348  0.0 ./test_c
26790 pts/1    S+     0:00      0     2 12425  1060  0.2 ./test_cpp
26843 pts/1    S+     0:00      0   275   580   256  0.0 ./test (Free Pascal)
26888 pts/1    S+     0:00      0   100  4295   608  0.1 sh test.sh
28340 pts/1    S+     0:00      0   896 11399  1376  0.2 bash test.sh
30040 pts/1    Sl+    0:00      0  1245 637138 9492  1.9 node test.nodejs
30167 pts/1    Sl+    0:00      0  2942 97437  5308  1.0 /usr/bin/cli ./test.exe
5969 pts/1    Sl+    0:00      0     2 1063041 15352  3.0 java Test


What does TRS, DRS and RSS mean? All of them are in kB. Btw. during these tests swap was not used.

TRS (Text Resident Set Size) - amount of physical memory allocated to executable code
DRS (Data Resident Set Size) - amount of physical memory allocated to other than executable code
RSS (Resident Set Size) - data memory allocated for this process (stack + data)

Most programs use same libraries and ideally these libraries exist in the memory space only once even for multiple processes. This is perfectly visible on PHP test above, it pre-loads all libraries under the sun and the process seems bloated. But if you were to start this process multiple times, your available memory would decrease only by RSS size, because everything else is shared with first instance.

Conclusion

Straight C is the winner hands down. The stripped program was 6.2kB and it's pretty much guaranteed that standard C library is already in memory, so your program adds only 348kB. I noticed this amount does go up by much even for several hundred line programs. Also gcc is already preinstalled on almost any system.

Free Pascal is not half bad either, it compiles statically, compiled file is 363k, program is fairly small comparing to other solutions though.

Next is ASH (sh on Debian). Keep in mind that almost every command in shell is a new process and so the execution will be slow and additional memory will be needed. Traditionally everything including true or [ was a command but modern shells have some commands built-in for efficiency (e.g. echo, printf, test, cd, eval, read, pwd, wait and others).

Lua is extremely light-weight comparing to others, the most light-weight scripting language.

Python is 3-5x heavier than Lua (code segment 15x), but I would still choose it for more complex than 200 lines programs for the libraries and features.

PHP and NodeJS are heavy. Unfortunately, these are the languages that move the internet. I guess they drive RAM cost down.

Mono C# seems to be comparable to Python as far as footprint. Similar TRS and RSS.
Reply
#2
That's only part of the story though - to be truly integrated a daemon needs the standard start, stop, refresh, status, etc., hooks for the various signals the os sends to it. It should also always report status properly ie error if its really an error, since there are other daemons that just watch to make sure the right stuff is always running, not duplicated, etc., and kill and restart things that misbehave. There is a standard C include that does this stuff, the lua not respecting ctrl-c is a huge red flag though, since that is one of the signals normally used to control a daemon.

So to fully compare them they should have all the correct features - I agree though C is going to win every time weight wise, BUT a heavier weight one might have the service interface stuff in a more mature state so its going to be more stable than a lightweight one you write from scratch.
--------------- ---- --- -- -  -
If things weren't meant to be modified, they would not come with wires attached.
Reply
#3
Jon, you are confusing System V init and daemon, aka a process that has no controlling terminal.

Goal of this article was to compare footprint of various toolkits, there will be another article about my daemon.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)