Skip to content

Instantly share code, notes, and snippets.

@elazarl
Created February 13, 2017 15:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elazarl/c7ff1be55e0d2bd008f6a46f606e239e to your computer and use it in GitHub Desktop.
Save elazarl/c7ff1be55e0d2bd008f6a46f606e239e to your computer and use it in GitHub Desktop.
Creating fragmentation on purpose to crash golang's GC
// This tiny program show how to cause fragmentation in golang, killing it
// even though no real memory is actually used.
// Compile:
// $ go build frag.go
// Run:
// $ time (setrlimit $[100*1000];./frag)
// .....(until it crashes)
package main
import "fmt"
const TIMES = 10 * 1000
func alloc_90_10(times, _90, _10 int, p *interface{}) {
for ; times > 0; times-- {
for i := 0; i < 9; i++ {
*p = make([]byte, _90)
}
*p = make([]byte, _10)
}
}
func main() {
// trick the compiler not to dicard the unused allocation
// IMPORTANT, as Go compiler becomes smarter, this little program might
// be compiled to no-op.
var x interface{}
dots := uint64(0)
for {
alloc_90_10(TIMES, 100, 47*1024, &x)
alloc_90_10(TIMES, 47*1024, 100, &x)
fmt.Print(".")
dots++
if dots%80 == 79 {
fmt.Println()
}
}
}
/*
Example run on go version go1.7.4 linux/amd64
Given virtual memory limit of 100MB:
⮀ time (ulimit -Sv 100000; ~/frag)
.....fatal error: runtime: out of memory
runtime stack:
runtime.throw(0x4a718a, 0x16)
/usr/local/go/src/runtime/panic.go:566 +0x95
runtime.sysMap(0xc425a00000, 0x100000, 0x7fc7e4e72100, 0x515e58)
/usr/local/go/src/runtime/mem_linux.go:219 +0x1d0
runtime.(*mheap).sysAlloc(0x4fd640, 0x100000, 0x4faac0)
/usr/local/go/src/runtime/malloc.go:407 +0x37a
runtime.(*mheap).grow(0x4fd640, 0x6, 0x0)
/usr/local/go/src/runtime/mheap.go:726 +0x62
runtime.(*mheap).allocSpanLocked(0x4fd640, 0x6, 0x7ffd18061aa0)
/usr/local/go/src/runtime/mheap.go:630 +0x4f2
runtime.(*mheap).alloc_m(0x4fd640, 0x6, 0x100000000, 0x7fc7e4e720a0)
/usr/local/go/src/runtime/mheap.go:515 +0xe0
runtime.(*mheap).alloc.func1()
/usr/local/go/src/runtime/mheap.go:579 +0x4b
runtime.systemstack(0x7ffd18061b10)
/usr/local/go/src/runtime/asm_amd64.s:314 +0xab
runtime.(*mheap).alloc(0x4fd640, 0x6, 0x10100000000, 0x2d)
/usr/local/go/src/runtime/mheap.go:580 +0x73
runtime.largeAlloc(0xbc00, 0x448301, 0xc420048f20)
/usr/local/go/src/runtime/malloc.go:774 +0x93
runtime.mallocgc.func1()
/usr/local/go/src/runtime/malloc.go:669 +0x3e
runtime.systemstack(0x4fa700)
/usr/local/go/src/runtime/asm_amd64.s:298 +0x79
runtime.mstart()
/usr/local/go/src/runtime/proc.go:1079
goroutine 1 [running]:
runtime.systemstack_switch()
/usr/local/go/src/runtime/asm_amd64.s:252 fp=0xc420048d70 sp=0xc420048d68
runtime.mallocgc(0xbc00, 0x48a6a0, 0xc420048e01, 0x40e64d)
/usr/local/go/src/runtime/malloc.go:670 +0x903 fp=0xc420048e10 sp=0xc420048d70
runtime.makeslice(0x48a6a0, 0xbc00, 0xbc00, 0x489560, 0xc42581c5a0, 0xbc00)
/usr/local/go/src/runtime/slice.go:57 +0x7b fp=0xc420048e68 sp=0xc420048e10
main.alloc_90_10(0x8af, 0xbc00, 0x64, 0xc420048f18)
/home/elazar/frag.go:10 +0x67 fp=0xc420048ee0 sp=0xc420048e68
main.main()
/home/elazar/frag.go:22 +0x94 fp=0xc420048f58 sp=0xc420048ee0
runtime.main()
/usr/local/go/src/runtime/proc.go:183 +0x1f4 fp=0xc420048fb0 sp=0xc420048f58
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2086 +0x1 fp=0xc420048fb8 sp=0xc420048fb0
( ulimit -Sv 100000; ~/frag; ) 6.14s user 0.38s system 126% cpu 5.157 total
*/
@alexanderankin
Copy link

something like this maybe?

javac Frag.java && java -Xmx1g -cp . Frag

import static java.lang.System.out;

public class Frag {
  static final int TIMES = 10 * 1000;

  public static void main(String[] args) {
    long dots = 0;
    byte[] x = new byte[0];

    out.println("starting");
    for (;;) {
      alloc_90_10(TIMES, 100, 47*1024, x);
      alloc_90_10(TIMES, 47*1024, 100, x);
      if (dots++ % 80 == 79) out.print(".");
    }
  }

  static void alloc_90_10(int times, int x90, int x10, byte[] p) {
    for (; times > 0; times--) {
      for (int i = 0; i < 9; i++) p = new byte[x90];
      p = new byte[x10];
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment