Skip to content

Instantly share code, notes, and snippets.

@leonid-shevtsov
Last active March 4, 2023 21:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leonid-shevtsov/4bb9383ae3f491afa40319267056581f to your computer and use it in GitHub Desktop.
Save leonid-shevtsov/4bb9383ae3f491afa40319267056581f to your computer and use it in GitHub Desktop.
Memory usage: Ruby vs Go vs JavaScript
package main
import (
"fmt"
"log"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
)
func getmem() int {
cmd := exec.Command("ps", "-o", "rss", fmt.Sprintf("%d", os.Getpid()))
output, err := cmd.Output()
if err != nil {
log.Fatal(err)
}
rssStr := strings.TrimSpace(strings.Split(string(output), "\n")[1])
rss, err := strconv.Atoi(rssStr)
if err != nil {
log.Fatal(err)
}
return rss
}
func measure[ItemType any](title string, count int, code func(int) ItemType) []ItemType {
runtime.GC()
startmem := getmem()
ary := make([]ItemType, count)
for i := 0; i < count; i++ {
ary[i] = code(i)
}
runtime.GC()
endmem := getmem()
fmt.Printf("%d %s: %d KB; %db per item\n", count, title, endmem-startmem, (endmem-startmem)*1024/count)
return ary
}
type StructType struct {
foo int
bar int
baz int
}
func main() {
measure("int", 10000000, func(i int) int {
return i
})
// measure("str", 10000000, func(i int) string {
// return fmt.Sprintf("%10d", i)
// })
// measure("const str", 10000000, func(i int) string {
// return "xxxxxxxxxx"
// })
// measure("const str generated", 10000000, func(i int) string {
// return strings.Repeat("x", 10)
// })
// measure("struct", 10000000, func(i int) StructType {
// return StructType{i, i + 1, i + 2}
// })
// measure("struct ptr", 10000000, func(i int) *StructType {
// return &StructType{i, i + 1, i + 2}
// })
// measure("map", 10000000, func(i int) map[string]int {
// return map[string]int{"foo": i, "bar": i + 1, "baz": i + 2}
// })
// measure("interface", 10000000, func(i int) interface{} {
// return StructType{i, i + 1, i + 2}
// })
}
// nodejs --expose-gc measure_js.js
const { memoryUsage } = require("process");
function measureMemory(title, count, gen) {
global.gc();
const startmem = memoryUsage.rss();
let result = new Array(count);
for (let i = 0; i < count; i++) {
result[i] = gen(i);
}
global.gc();
const endmem = memoryUsage.rss();
console.log(
`${count} ${title}: ${(endmem - startmem) / 1024} KB; ${Math.round(
(endmem - startmem) / count
)}b per item`
);
return result;
}
class CustomClass {
constructor(i) {
this.foo = i;
this.bar = i + 1;
this.baz = i + 2;
}
}
// measureMemory("int", 10000000, (i) => i);
// measureMemory("float", 10000000, (i) => 1.0 / i);
// measureMemory("str", 10000000, (i) => i.toString().padStart(10));
// measureMemory("str const", 10000000, (i) => "xxxxxxxxxx");
measureMemory("ad-hoc obj", 10000000, (i) => ({
foo: i,
// bar: i + 1,
// baz: i + 2,
// abc: i + 2,
// sdf: i + 2,
// asa: i + 2,
// per: i + 2,
// sff: i + 2,
// sss: i + 2,
}));
// measureMemory("custom class", 10000000, (i) => new CustomClass(i));
// 1, 47
// 2,54
// 3, 62
// 4,70
// 5, 78
def getmem
`ps -o rss #{Process.pid}`.lines.last.strip.to_i
end
def measure_memory(title, count, &block)
GC.start
startmem = getmem
result = Array.new(count, &block)
GC.start
endmem = getmem
puts "#{count} #{title}: #{endmem - startmem} KB; #{(endmem - startmem)*1024/count}b per item"
result
end
StructClass = Struct.new(:foo,:bar,:baz)
class CustomClass
attr_accessor :foo, :bar, :baz
def initialize(foo, bar, baz)
@foo, @bar, @baz = foo, bar, baz
end
end
measure_memory("int array", 100_000_000) { |i| i }
# measure_memory("str_array 10M") do
# Array.new(10_000_000) { |i| format('%10d', i) }
# end
# measure_memory("str_array_const 10M") do
# Array.new(10_000_000) { 'xxxxxxxxxx' }
# end
# measure_memory("symbol_array 10M") do
# Array.new(10_000_000) { :xxxxxxxxxx }
# end
# measure_memory("struct array", 10_000_000) { |i| StructClass.new(i, i+1, i+2) }
# measure_memory("class", 10_000_000) { |i| CustomClass.new(i, i+1, i+2) }
# measure_memory("hash ", 10_000_000) { |i| {foo: i, bar: i+1, baz: i+2} }
# measure_memory("str hash ", 10_000_000) { |i| {"foo" => i, "bar" => i+1, "baz" => i+2} }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment