Skip to content

Instantly share code, notes, and snippets.

@msoap
Last active April 11, 2018 07:13
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msoap/8123207 to your computer and use it in GitHub Desktop.
Save msoap/8123207 to your computer and use it in GitHub Desktop.
Go vs Perl memory usage
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
use utf8;
use open ":std" => ":utf8";
our $CHART_SCALE = 2.5;
# --------------------------------------------------------------------
sub main {
system("go build test_memory.go");
my $stat = {};
for my $type (qw/map_int_key_of_string
map_string_key_of_string
map_int_key_of_int
map_string_key_of_int
slice_of_string
slice_of_int/
)
{
for my $nums (qw/500 700 1000 1500/) {
for my $lang (qw/perl go/) {
my $exe = $lang eq 'perl'
? 'perl ./test_memory.pl'
: $lang eq 'go'
? './test_memory'
: die;
print "$type / $nums / $lang:";
my $memory = qx/$exe $type $nums | awk '\$1 == "memory:" {print \$2}'/ + 0;
print " $memory MB\n";
$stat->{$type}->{$nums}->{$lang} = $memory;
}
}
}
print "----------------------\n";
for my $type (sort keys %$stat) {
printf "%s:\n", {map_int_key_of_string => '{int}->{int} = string'
, map_string_key_of_string => '{string}->{string} = string'
, map_string_key_of_int => '{string}->{string} = int'
, map_int_key_of_int => '{int}->{int} = int'
, slice_of_string => '[int]->[int] = string'
, slice_of_int => '[int]->[int] = int'
}->{$type};
print " lang (keys² q-ty): MB of memory\n";
for my $nums (sort {$b <=> $a} keys %{$stat->{$type}}) {
printf " Go (%4i²): %7s %s\n", $nums, $stat->{$type}->{$nums}->{go}, chr(9632) x int($stat->{$type}->{$nums}->{go} / $CHART_SCALE);
printf " Perl (%4i²): %7s %s\n", $nums, $stat->{$type}->{$nums}->{perl}, chr(9632) x int($stat->{$type}->{$nums}->{perl} / $CHART_SCALE);
print "\n";
}
print "\n";
}
}
# --------------------------------------------------------------------
main();

Go vs Perl memory usage

{int}->{int} = int:
  lang (keys² q-ty): MB of memory
  Go   (1500²):   66.38 ■■■■■■■■■■■■■■■■■■■■■■■■■■
  Perl (1500²):  131.46 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

  Go   (1000²):    40.8 ■■■■■■■■■■■■■■■■
  Perl (1000²):   57.65 ■■■■■■■■■■■■■■■■■■■■■■■

  Go   ( 700²):   17.52 ■■■■■■■
  Perl ( 700²):   31.59 ■■■■■■■■■■■■

  Go   ( 500²):   12.14 ■■■■
  Perl ( 500²):   16.89 ■■■■■■


{int}->{int} = string:
  lang (keys² q-ty): MB of memory
  Go   (1500²):  150.53 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  Perl (1500²):  176.25 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

  Go   (1000²):   86.64 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  Perl (1000²):   81.55 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

  Go   ( 700²):   37.82 ■■■■■■■■■■■■■■■
  Perl ( 700²):   46.72 ■■■■■■■■■■■■■■■■■■

  Go   ( 500²):    23.8 ■■■■■■■■■
  Perl ( 500²):    24.6 ■■■■■■■■■


{string}->{string} = int:
  lang (keys² q-ty): MB of memory
  Go   (1500²):  143.53 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  Perl (1500²):  131.52 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

  Go   (1000²):    78.5 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  Perl (1000²):    57.7 ■■■■■■■■■■■■■■■■■■■■■■■

  Go   ( 700²):   34.82 ■■■■■■■■■■■■■
  Perl ( 700²):   31.62 ■■■■■■■■■■■■

  Go   ( 500²):   21.99 ■■■■■■■■
  Perl ( 500²):    16.9 ■■■■■■


{string}->{string} = string:
  lang (keys² q-ty): MB of memory
  Go   (1500²):  213.76 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  Perl (1500²):  176.22 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

  Go   (1000²):   109.3 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  Perl (1000²):    81.2 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

  Go   ( 700²):   50.53 ■■■■■■■■■■■■■■■■■■■■
  Perl ( 700²):   46.75 ■■■■■■■■■■■■■■■■■■

  Go   ( 500²):   30.57 ■■■■■■■■■■■■
  Perl ( 500²):   24.62 ■■■■■■■■■


[int]->[int] = int:
  lang (keys² q-ty): MB of memory
  Go   (1500²):   20.32 ■■■■■■■■
  Perl (1500²):   81.75 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

  Go   (1000²):    9.96 ■■■
  Perl (1000²):    39.7 ■■■■■■■■■■■■■■■

  Go   ( 700²):    5.96 ■■
  Perl ( 700²):    19.3 ■■■■■■■

  Go   ( 500²):    3.64 ■
  Perl ( 500²):   11.04 ■■■■


[int]->[int] = string:
  lang (keys² q-ty): MB of memory
  Go   (1500²):   98.27 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  Perl (1500²):  127.77 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

  Go   (1000²):    44.2 ■■■■■■■■■■■■■■■■■
  Perl (1000²):   63.98 ■■■■■■■■■■■■■■■■■■■■■■■■■

  Go   ( 700²):   22.22 ■■■■■■■■
  Perl ( 700²):   34.78 ■■■■■■■■■■■■■

  Go   ( 500²):   11.58 ■■■■
  Perl ( 500²):   18.79 ■■■■■■■
package main
import (
"fmt"
"os"
"os/exec"
"path"
"strconv"
"strings"
)
const NUMS = 1500
//------------------------------------
func test_map_string_key_of_string(name string, nums int) interface{} {
fmt.Println("Start", name)
var hash = make(map[string]map[string]string, nums)
for i := 0; i < nums; i++ {
str_i := fmt.Sprintf("%d", i)
hash["key_"+str_i] = make(map[string]string, nums)
for j := 0; j < nums; j++ {
str_j := fmt.Sprintf("%d", j)
hash["key_"+str_i]["key_j_"+str_j] = "string_" + str_i + "_" + str_j
}
}
fmt.Println("Finish")
return hash
}
//------------------------------------
func test_map_int_key_of_string(name string, nums int) interface{} {
fmt.Println("Start", name)
var hash = make(map[int]map[int]string, nums)
for i := 0; i < nums; i++ {
hash[i] = make(map[int]string, nums)
for j := 0; j < nums; j++ {
hash[i][j] = "string_" + fmt.Sprintf("%d", i) + "_" + fmt.Sprintf("%d", j)
}
}
fmt.Println("Finish")
return hash
}
//------------------------------------
func test_map_string_key_of_int(name string, nums int) interface{} {
fmt.Println("Start", name)
var hash = make(map[string]map[string]int, nums)
for i := 0; i < nums; i++ {
str_i := fmt.Sprintf("%d", i)
hash["key_"+str_i] = make(map[string]int, nums)
for j := 0; j < nums; j++ {
str_j := fmt.Sprintf("%d", j)
hash["key_"+str_i]["key_j_"+str_j] = i * nums + j
}
}
fmt.Println("Finish")
return hash
}
//------------------------------------
func test_map_int_key_of_int(name string, nums int) interface{} {
fmt.Println("Start", name)
var hash = make(map[int]map[int]int, nums)
for i := 0; i < nums; i++ {
hash[i] = make(map[int]int, nums)
for j := 0; j < nums; j++ {
hash[i][j] = i * nums + j
}
}
fmt.Println("Finish")
return hash
}
//------------------------------------
func test_slice_of_string(name string, nums int) interface{} {
fmt.Println("Start", name)
var array = make([][]string, nums)
for i := 0; i < nums; i++ {
array[i] = make([]string, nums)
for j := 0; j < nums; j++ {
array[i][j] = "string_" + fmt.Sprintf("%d", i) + "_" + fmt.Sprintf("%d", j)
}
}
fmt.Println("Finish")
return array
}
//------------------------------------
func test_slice_of_int(name string, nums int) interface{} {
fmt.Println("Start", name)
var array = make([][]int, nums)
for i := 0; i < nums; i++ {
array[i] = make([]int, nums)
for j := 0; j < nums; j++ {
array[i][j] = i * nums + j
}
}
fmt.Println("Finish")
return array
}
//------------------------------------
func test_array(name string, nums int) interface{} {
fmt.Println("Start", name)
var array [NUMS][NUMS]string
for i := 0; i < nums; i++ {
// array[i] = make([]string, nums)
for j := 0; j < nums; j++ {
array[i][j] = "string_" + fmt.Sprintf("%d", i) + "_" + fmt.Sprintf("%d", j)
}
}
fmt.Println("Finish")
return array
}
//------------------------------------
func keys(hash map[string]func(string, int)interface{}) []string {
result := []string{}
for key, _ := range hash {
result = append(result, key)
}
return result
}
//------------------------------------
func main() {
test_type := ""
if len(os.Args) > 1 {
test_type = os.Args[1]
}
nums := NUMS
if len(os.Args) == 3 {
nums_arg, err := strconv.Atoi(os.Args[2])
if err == nil && nums_arg > 0 {
nums = nums_arg
}
}
fmt.Printf("nums: %d²\n", nums)
test_functions := map[string]func(string, int)interface{}{"map_int_key_of_string": test_map_int_key_of_string,
"map_string_key_of_string": test_map_string_key_of_string,
"map_int_key_of_int": test_map_int_key_of_int,
"map_string_key_of_int": test_map_string_key_of_int,
"slice_of_string": test_slice_of_string,
"slice_of_int": test_slice_of_int,
"array": test_array}
var result interface{}
if test_function, found := test_functions[test_type]; found {
result = test_function(test_type, nums)
fmt.Printf("type is: %T\n", result)
} else {
fmt.Printf("usage: %s %s [NUMS]\n", path.Base(os.Args[0]), strings.Join(keys(test_functions), "|"))
return
}
cmd_out, err := exec.Command("sh", "-c", "ps aux | awk '$2 == " + strconv.Itoa(os.Getpid()) + " {print $6}'").Output()
if err != nil {
fmt.Println("Error:", err)
return
}
memory_kb, _ := strconv.Atoi(strings.TrimSpace(string(cmd_out)))
fmt.Printf("memory: %.2f MB\n", float32(memory_kb) / 1024.0)
}
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
our $NUMS = 1500;
# --------------------------------------------------------------------
sub test_map_string_key_of_string {
my $name = shift;
my $nums = shift;
print "Start $name\n";
my $hash = {};
for (my $i = 0; $i < $nums; $i++) {
$hash->{"key_" . $i} = {};
for (my $j = 0; $j < $nums; $j++) {
$hash->{"key_" . $i}->{"key_j_" . $j} = "string_${i}_${j}";
}
}
print "Finish\n";
}
# --------------------------------------------------------------------
sub test_map_int_key_of_string {
my $name = shift;
my $nums = shift;
print "Start $name\n";
my $hash = {};
for (my $i = 0; $i < $nums; $i++) {
$hash->{$i} = {};
for (my $j = 0; $j < $nums; $j++) {
$hash->{$i}->{$j} = "string_${i}_${j}";
}
}
print "Finish\n";
}
# --------------------------------------------------------------------
sub test_map_string_key_of_int {
my $name = shift;
my $nums = shift;
print "Start $name\n";
my $hash = {};
for (my $i = 0; $i < $nums; $i++) {
$hash->{"key_" . $i} = {};
for (my $j = 0; $j < $nums; $j++) {
$hash->{"key_" . $i}->{"key_j_" . $j} = $i * $nums + $j;
}
}
print "Finish\n";
}
# --------------------------------------------------------------------
sub test_map_int_key_of_int {
my $name = shift;
my $nums = shift;
print "Start $name\n";
my $hash = {};
for (my $i = 0; $i < $nums; $i++) {
$hash->{$i} = {};
for (my $j = 0; $j < $nums; $j++) {
$hash->{$i}->{$j} = $i * $nums + $j;
}
}
print "Finish\n";
}
# --------------------------------------------------------------------
sub test_slice_of_string {
my $name = shift;
my $nums = shift;
print "Start $name\n";
my $array = [];
for (my $i = 0; $i < $nums; $i++) {
for (my $j = 0; $j < $nums; $j++) {
$array->[$i]->[$j] = "string_${i}_${j}";
}
}
print "Finish\n";
}
# --------------------------------------------------------------------
sub test_slice_of_int {
my $name = shift;
my $nums = shift;
print "Start $name\n";
my $array = [];
for (my $i = 0; $i < $nums; $i++) {
for (my $j = 0; $j < $nums; $j++) {
$array->[$i]->[$j] = $i * $nums + $j;
}
}
print "Finish\n";
}
# --------------------------------------------------------------------
sub main {
my $nums = $ARGV[1] && $ARGV[1] =~ /^\d+$/ && $ARGV[1] > 0 ? $ARGV[1] : $NUMS;
print "nums: $nums\n";
my $test_functions = {
map_int_key_of_string => \&test_map_int_key_of_string
, map_string_key_of_string => \&test_map_string_key_of_string
, map_string_key_of_int => \&test_map_string_key_of_int
, map_int_key_of_int => \&test_map_int_key_of_int
, slice_of_string => \&test_slice_of_string
, slice_of_int => \&test_slice_of_int
};
if ($ARGV[0]
&& $ARGV[0]
&& defined $test_functions->{$ARGV[0]}
)
{
$test_functions->{$ARGV[0]}->($ARGV[0], $nums);
} else {
printf("usage: $0 %s [NUMS]\n", join("|", keys %$test_functions));
return;
}
my $memory_kb = qx/ps aux | awk '\$2 == $$ {print \$6}'/;
printf("memory: %.2f MB\n", $memory_kb / 1024);
}
# --------------------------------------------------------------------
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment