Upper Bounds on Memory Usage for
Garbage-Collected Languages
Elvira Albert
1
, Samir Genaim
1
, Miguel G´
omez-Zamalloa
1
Puri Arenas
1
, Germ´an Puebla
2
and Damiano Zanardini
2
(1)Complutense University of Madrid (Spain)
(2) Technical University of Madrid (Spain)
Cost Analysis
is the automatic study of
program efficiency
(or the
resource consumption
).
◮
Its aim is to statically
estimate the cost of a program execution in
Introduction
Cost Analysis
is the automatic study of
program efficiency
(or the
resource consumption
).
◮
Its aim is to statically
estimate the cost of a program execution in
terms of the size of its input args.
The cost can be defined w.r.t. different
cost models
:
◮
number of instructions executed
◮memory allocated
Cost Analysis
is the automatic study of
program efficiency
(or the
resource consumption
).
◮
Its aim is to statically
estimate the cost of a program execution in
terms of the size of its input args.
The cost can be defined w.r.t. different
cost models
:
◮
number of instructions executed
◮memory allocated
◮
number calls to certain methods: billable events on a mobile
Finding the exact cost of programs is
undecidable, but it is possible to
infer useful information (
bounds
):
Introduction
Cost Analysis
is the automatic study of
program efficiency
(or the
resource consumption
).
◮
Its aim is to statically
estimate the cost of a program execution in
terms of the size of its input args.
The cost can be defined w.r.t. different
cost models
:
◮
number of instructions executed
◮memory allocated
◮
number calls to certain methods: billable events on a mobile
Finding the exact cost of programs is
undecidable, but it is possible to
infer useful information (
bounds
):
◮
Upper bounds
: a program runs within the resources available.
◮Lower bounds
: useful for scheduling distributed execution.
0: new Cons
Cons.copy()
3: dup
7: astore
4: invokespecial
. . .
. . .
27: aload
28: areturn
Size
SOLVER
CFG
Relations
Cost Relations
BYTECODE PROGRAM
RBR
COST MODEL
THE COSTA SYSTEM
UPPER BOUND
a
C(a) = 8*2 O(2)
COSTA: Cost Analyzer for Java Bytecode
0: new Cons
Cons.copy()
3: dup
7: astore
4: invokespecial
. . .
. . .
27: aload
28: areturn
Size
SOLVER
CFG
Relations
Cost Relations
BYTECODE PROGRAM
RBR
COST MODEL
THE COSTA SYSTEM
UPPER BOUND
a
C(a) = 8*2 O(2)
a
For mobile code, we do not have access to source code.
0: new Cons
Cons.copy()
3: dup
7: astore
4: invokespecial
. . .
. . .
27: aload
28: areturn
Size
SOLVER
CFG
Relations
Cost Relations
BYTECODE PROGRAM
RBR
COST MODEL
THE COSTA SYSTEM
UPPER BOUND
a
C(a) = 8*2 O(2)
a
For mobile code, we do not have access to source code.
HEAP:
Total Allocation Analysis
Symbolic
cost model
for heap consumption,
size
(
Tree
),
size
(
Integer
)..
We get upper bounds of the
total
allocated memory.
Symbolic
cost model
for heap consumption,
size
(
Tree
),
size
(
Integer
)..
We get upper bounds of the
total
allocated memory.
In presence of
garbage collection (GC)
, it is a too pessimistic
estimation of the actual memory consumption.
PEAK:
Live Heap Space Analysis
Aims at approximating the maximum or
peak
heap usage.
Scope-based GC model:
1
Reclaims unreachable memory when methods return. This assumption
can be refined up to an ideal GC.
2
Collects unreachable objects which have been created during the
execution of the corresponding method call and not before.
From Java to Intermediate representation
class
Test
{
staticTree m(intn){
if( n>0 )return
newTree(m(n-1),m(n-1),f(n));
elsereturn null;
}
static intf(intn){
inta=0,i=n; for(; n>1 ; n=n/2 )
a += g(n).intValue(); for(; i>1; i=i/2)
a *= h(i).intValue(); returna;
}
staticInteger g(int n){
Integer x=newInteger(n); returnnewInteger(x.intValue()+1);
}
staticTree m(intn){
if( n>0 )return
newTree(m(n-1),m(n-1),f(n));
elsereturn null;
}
static intf(intn){
inta=0,i=n; for(; n>1 ; n=n/2 )
a += g(n).intValue(); for(; i>1; i=i/2)
a *= h(i).intValue(); returna;
}
staticInteger g(int n){
Integer x=newInteger(n); returnnewInteger(x.intValue()+1);
}
staticLong h(int n){
returnnewLong(n-1);
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1
,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1
,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
a
:=
0
,
i
:=
n
,
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)
,
f
d
(
h
i
,
a
i
,
h
i
,
a
i
)
,
r
:=
a
.
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)::=
n
>
1
,
g
(
h
n
i
,
h
s
0
i
)
,
intValue
1
(
h
s
0
i
,
h
s
0
i
)
a
:=
a
+
s
0
,
n
:=
n
/
2
,
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)
.
From Java to Intermediate representation
class
Test
{
staticTree m(intn){ if( n>0 )return
newTree(m(n-1),m(n-1),f(n));
elsereturn null; }
static intf(intn){
inta=0,i=n; for(; n>1 ; n=n/2 )
a += g(n).intValue(); for(; i>1; i=i/2)
a *= h(i).intValue(); returna;
}
staticInteger g(int n){
Integer x=newInteger(n); returnnewInteger(x.intValue()+1);
}
staticLong h(int n){
m
(
h
n
i
,
h
r
i
)::=
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
f
(
h
n
i
,
h
r
i
)::=
a
:=
0
,
i
:=
n
,
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)
,
f
d
(
h
i
,
a
i
,
h
i
,
a
i
)
,
r
:=
a
.
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)::=
n
>
1
,
g
(
h
n
i
,
h
s
0
i
)
,
intValue
1
(
h
s
0
i
,
h
s
0
i
)
a
:=
a
+
s
0
,
n
:=
n
/
2
,
staticTree m(intn){
if( n>0 )return
newTree(m(n-1),m(n-1),f(n));
elsereturn null;
}
static intf(intn){
inta=0,i=n; for(; n>1 ; n=n/2 )
a += g(n).intValue(); for(; i>1; i=i/2)
a *= h(i).intValue(); returna;
}
staticInteger g(int n){
Integer x=newInteger(n); returnnewInteger(x.intValue()+1);
}
staticLong h(int n){
returnnewLong(n-1);
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1
,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1
,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
a
:=
0
,
i
:=
n
,
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)
,
f
d
(
h
i
,
a
i
,
h
i
,
a
i
)
,
r
:=
a
.
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)::=
n
>
1
,
g
(
h
n
i
,
h
s
0
i
)
,
intValue
1
(
h
s
0
i
,
h
s
0
i
)
a
:=
a
+
s
0
,
n
:=
n
/
2
,
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)
.
From Java to Intermediate representation
class
Test
{
staticTree m(intn){
if( n>0 )return
newTree(m(n-1),m(n-1),f(n));
elsereturn null;
}
static intf(intn){
inta=0,i=n; for(; n>1 ; n=n/2 )
a += g(n).intValue(); for(; i>1; i=i/2)
a *= h(i).intValue(); returna;
}
staticInteger g(int n){
Integer x=newInteger(n); returnnewInteger(x.intValue()+1);
}
staticLong h(int n){
m
(
h
n
i
,
h
r
i
)::=
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
f
(
h
n
i
,
h
r
i
)::=
a
:=
0
,
i
:=
n
,
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)
,
f
d
(
h
i
,
a
i
,
h
i
,
a
i
)
,
r
:=
a
.
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)::=
n
>
1
,
g
(
h
n
i
,
h
s
0
i
)
,
intValue
1
(
h
s
0
i
,
h
s
0
i
)
a
:=
a
+
s
0
,
n
:=
n
/
2
,
staticTree m(intn){
if( n>0 )return
newTree(m(n-1),m(n-1),f(n));
elsereturn null; }
static intf(intn){
inta=0,i=n; for(; n>1 ; n=n/2 )
a += g(n).intValue(); for(; i>1; i=i/2)
a *= h(i).intValue(); returna;
}
staticInteger g(int n){
Integer x=newInteger(n); returnnewInteger(x.intValue()+1);
}
staticLong h(int n){
returnnewLong(n-1);
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1
,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1
,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
a
:=
0
,
i
:=
n
,
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)
,
f
d
(
h
i
,
a
i
,
h
i
,
a
i
)
,
r
:=
a
.
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)::=
n
>
1
,
g
(
h
n
i
,
h
s
0
i
)
,
intValue
1
(
h
s
0
i
,
h
s
0
i
)
a
:=
a
+
s
0
,
n
:=
n
/
2
,
f
c
(
h
n
,
a
i
,
h
n
,
a
i
)
.
From Java to Intermediate representation
class
Test
{
staticTree m(intn){
if( n>0 )return
newTree(m(n-1),m(n-1),f(n));
elsereturn null;
}
static intf(intn){ inta=0,i=n; for(; n>1 ; n=n/2 )
a += g(n).intValue(); for(; i>1; i=i/2)
a *= h(i).intValue(); returna;
}
staticInteger g(int n){
Integer x=newInteger(n); returnnewInteger(x.intValue()+1);
}
staticLong h(int n){
m
(
h
n
i
,
h
r
i
)::=
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1
,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1
,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
f
(
h
n
i
,
h
r
i
)::=
a
:=
0,
i
:=
n,
f
c
(
h
n,
a
i
,
h
n,
a
i
)
,
f
d
(
h
i,
a
i
,
h
i,
a
i
)
,
r
:=
a.
f
c(
h
n,
a
i
,
h
n,
a
i
)::=
n
>
1
,
g
(
h
n
i
,
h
s
0
i
)
,
intValue
1
(
h
s
0
i
,
h
s
0
i
)
a
:=
a
+
s
0
,
staticTree m(intn){
if( n>0 )return
newTree(m(n-1),m(n-1),f(n));
elsereturn null;
}
static intf(intn){
inta=0,i=n;
for(; n>1 ; n=n/2 ) a += g(n).intValue();
for(; i>1; i=i/2) a *= h(i).intValue(); returna;
}
staticInteger g(int n){
Integer x=newInteger(n); returnnewInteger(x.intValue()+1);
}
staticLong h(int n){
returnnewLong(n-1);
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1
,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1
,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
a
:=
0
,
i
:=
n
,
f
c
(
h
n,
a
i
,
h
n,
a
i
)
,
f
d
(
h
i
,
a
i
,
h
i
,
a
i
)
,
r
:=
a
.
f
c(
h
n,
a
i
,
h
n,
a
i
)::=
n
>
1
,
g
(
h
n
i
,
h
s
0
i
)
,
intValue
1
(
h
s
0
i
,
h
s
0
i
)
a
:=
a
+
s
0
,
n
:=
n/2,
f
c
(
h
n,
a
i
,
h
n,
a
i
)
.
From Intermediate representation to cost equations
m
(
h
n
i
,
h
r
i
)::=
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1
,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1
,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
m
(
n
)=
size
(
Tree
1
)+
{n
>
0
}
m
(
n
−
1
)+
m
(
n
−
1
)+
f
(
n
)+
init
(
1
,
n
−
1
,
n
−
1
,
s
3
)
m
(
h
n
i
,
h
r
i
)
::=
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1
,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1
,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)
::=
n
≤
0
,
r
:= null
.
m
(
n
)
=
size
(
Tree
1
)+
{n
>
0
}
m
(
n
−
1
)+
m
(
n
−
1
)+
f
(
n
)+
init
(
1
,
n
−
1
,
n
−
1
,
s
3
)
From Intermediate representation to cost equations
m
(
h
n
i
,
h
r
i
)::=
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1
,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1
,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
m
(
n
)=
size
(
Tree
1
)+
{
n
>
0
}
m
(
n
−
1
)+
m
(
n
−
1
)+
f
(
n
)+
init
(
1
,
n
−
1
,
n
−
1
,
s
3
)
m
(
h
n
i
,
h
r
i
)::=
n
>
0
,
s
0
:=
new
Tree
1
;
s
1
:=
n
−
1
,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1
,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
m
(
n
)=
size
(
Tree
1
)
+
{n
>
0
}
m
(
n
−
1
)+
m
(
n
−
1
)+
f
(
n
)+
init
(
1
,
n
−
1
,
n
−
1
,
s
3
)
From Intermediate representation to cost equations
m
(
h
n
i
,
h
r
i
)::=
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1
,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1
,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
m
(
n
)=
size
(
Tree
1
)+
{n
>
0
}
m
(
n
−
1
)
+
m
(
n
−
1
)
+
f
(
n
)
+
init
(
1,
n
−
1,
n
−
1,
s
3
)
m
(
h
n
i
,
h
r
i
)::=
n
>
0
,
s
0
:= new
Tree
1
;
s
1
:=
n
−
1
,
m
(
h
s
1
i
,
h
s
1
i
)
,
s
2
:=
n
−
1
,
m
(
h
s
2
i
,
h
s
2
i
)
,
f
(
h
n
i
,
h
s
3
i
)
,
init
(
h
s
0
,
s
1
,
s
2
,
s
3
i
,
hi
)
,
r
=
s
0
.
m
(
h
n
i
,
h
r
i
)::=
n
≤
0
,
r
:= null
.
m
(
n
)=
size
(
Tree
1
)
+
{n
>
0
}
m
(
n
−
1
)+
m
(
n
−
1
)+
f
(
n
)+
init
(
1
,
n
−
1
,
n
−
1
,
s
3
)
m
(
n
)=
0
{n≤
0
}
f
(
n
)=
f
c
(
n
,
0
) +
f
d
(
n
,
a
′
)
{}
f
c
(
n
,
a
)=
g
(
n
)+
f
c
(
n
/
2
,
a
′
)
{n
>
1
}
f
c
(
n
,
a
)=
0
{n≤
1
}
f
d
(
i
,
a
)=
h
(
i
)+
f
d
(
i
/
2
,
a
′
)
{i
>
1
}
f
d
(
i
,
a
)=
0
{i≤
0
}
g
(
n
)=
size
(
Integer
2
)
+
size
(
Integer
3
)
{}
h
(
n
)=
size
(
Long
4
)
{}
From Cost Relations to Upper Bounds
solutions computed for f
total
(
f
) =
total
(
f
c
) +
total
(
f
d
)
for
(; n
>
1 ; n=n/2 ) a += g(n).intValue();
for
(; i
>
1 ; i=i/2 ) a *= h(i).intValue();
f
c
(
n
) =
log
(
n
)
∗
(
size
(
Integer
3
) +
size
(
Integer
2
))
solutions computed for f
total
(
f
) =
total
(
f
c
) +
total
(
f
d
)
for
(; n
>
1 ; n=n/2 ) a += g(n).intValue();
for
(; i
>
1 ; i=i/2 ) a *= h(i).intValue();
f
c
(
n
) =
log
(
n
)
∗
(
size
(
Integer
3
) +
size
(
Integer
2
))
f
d
(
i
) =
log
(
i
)
∗
size
(
Long
4
)
solutions computed for m
m
(
n
) = 2
n
∗
(
total
(
f
)
|
{z
}
exp times
+
size
(
Tree
1
))
Why Live Heap Space Analysis is Different?
Basic idea in total allocation:
Basic idea in total allocation:
total
(
{
m
1
;
m
2
}
) =
total
(
m
1
) +
total
(
m
2
)
Why Live Heap Space Analysis is Different?
Basic idea in total allocation:
total
(
{
m
1
;
m
2
}
) =
total
(
m
1
) +
total
(
m
2
)
While total memory allocation is an
accumulative
resource, the live heap
space
increases and decreases
along an execution
Basic idea in live Heap Space Analysis:
Basic idea in total allocation:
total
(
{
m
1
;
m
2
}
) =
total
(
m
1
) +
total
(
m
2
)
While total memory allocation is an
accumulative
resource, the live heap
space
increases and decreases
along an execution
Basic idea in live Heap Space Analysis:
peak
(
{
m
1
;
m
2
}
) =
max
(
peak
(
m
1
)
,
escaped
(
m
1
)
+
peak
(
m
2
))
1
STEP 1:
Escaped memory analysis
Example
class
Test
{
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a +=g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
staticLong h(int n){
return newLong(n-1);
1
Example
class
Test
{
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
1 2
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a +=g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
staticLong h(int n){
return newLong(n-1);
1 2
Example
class
Test
{
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
1 2 3
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a +=g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
staticLong h(int n){
return newLong(n-1);
1 2 3
Example
class
Test
{
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
1 2 3
log(n)
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a +=g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
staticLong h(int n){
return newLong(n-1);
1 2 3
log(n)
Example
class
Test
{
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
1 2 3
log(n)
1
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *=h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
staticLong h(int n){
return newLong(n-1);
1 2 3
log(n)
1
Example
class
Test
{
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
1 2 3
log(n)
1 2
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *=h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
staticLong h(int n){
return newLong(n-1);
1 2 3
log(n)
1 2
Example
class
Test
{
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
1 2 3
log(n)
1 2 3
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *=h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
staticLong h(int n){
return newLong(n-1);
1 2 3
log(n)
1 2 3
Example
class
Test
{
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
1 2 3
log(n)
1 2 3
log(n)
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *=h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
staticLong h(int n){
return newLong(n-1);
1 2 3
log(n)
1 2 3
log(n)
Example
class
Test
{
staticTree m(intn){
if( n>0 )return newTree(m(n-1),m(n-1),f(n)); elsereturn null;
}
static intf(intn){
inta=0,i=n;
•for(;n>1;n=n/2)
•a += g(n).intValue();
•for(; i>1; i=i/2)
•a *= h(i).intValue();
•returna;
}
staticInteger g(int n){
Integer x=newInteger(n); return newInteger(x.intValue()+1);
}
1 2 3
log(n)
1 2 3
log(n)
Infer upper bounds on the total memory consumption
Remove from the bounds the
collectable
objects
Step 1: Inference of Escaped Memory Bounds
Infer upper bounds on the total memory consumption
Remove from the bounds the
collectable
objects
The set of collectable objects can be approximated from the
information computed by
escape
analysis
collectable objects from
m
•
static
Tree m(
int
n)
{
if
( n
>
0 )
return new
Tree(m(n-1),m(n-1),f(n));
else
return null
;
}
•
static int
f(
int
n)
{
int
a=0,i=n;
•
for
(; n
>
1;n=n/2 )
a += g(n).intValue();
•
for
(; i
>
1; i=i/2)
a *= h(i).intValue();
return
a;
}
•
static
Integer g(int n)
{
Integer x=
new
Integer
2(n);
return new
Integer
3(x.intValue()+1);
}
•
static
Long h(int n)
{
return new
Long
4(n-1);
}
}
// end of class Test
c ollectable
(g) =
{Integer
2}
c ollectable
(h) =
∅
c ollectable
(f
) =
{Integer
2,
Integer
3
,
Long
Collectable Objects
class
Test
{
•
static
Tree m(
int
n)
{
if
( n
>
0 )
return new
Tree(m(n-1),m(n-1),f(n));
else
return null
;
}
•
static int
f(
int
n)
{
int
a=0,i=n;
•
for
(; n
>
1;n=n/2 )
a += g(n).intValue();
•
for
(; i
>
1; i=i/2)
a *= h(i).intValue();
return
a;
}
•
static
Integer g(int n)
{
Integer x=
new
Integer
2(n)
;
return
new
Integer
3(x.intValue()+1)
;
}
•
static
Long h(int n)
{
return new
Long
4(n-1);
}
}
// end of class Test
c ollectable
(
g
) =
{
Integer
2•
static
Tree m(
int
n)
{
if
( n
>
0 )
return new
Tree(m(n-1),m(n-1),f(n));
else
return null
;
}
•
static int
f(
int
n)
{
int
a=0,i=n;
•
for
(; n
>
1;n=n/2 )
a += g(n).intValue();
•
for
(; i
>
1; i=i/2)
a *= h(i).intValue();
return
a;
}
•
static
Integer g(int n)
{
Integer x=
new
Integer
2(n);
return new
Integer
3(x.intValue()+1);
}
•
static
Long h(int n)
{
return
new
Long
4(n-1)
;
}
}
// end of class Test
c ollectable
(g) =
{Integer
2}
c ollectable
(
h
) =
∅
c ollectable
(f
) =
{Integer
2,
Integer
3
,
Long
Collectable Objects
class
Test
{
•
static
Tree m(
int
n)
{
if
( n
>
0 )
return new
Tree(m(n-1),m(n-1),f(n));
else
return null
;
}
•
static int
f(
int
n)
{
int
a=0,i=n;
•
for
(; n
>
1;n=n/2 )
a += g(n).intValue();
•
for
(; i
>
1; i=i/2)
a *= h(i).intValue();
return
a;
}
•
static
Integer g(int n)
{
Integer x=
new
Integer
2(n)
;
return
new
Integer
3(x.intValue()+1)
;
}
•
static
Long h(int n)
{
return
new
Long
4(n-1)
;
}
}
// end of class Test
•
static
Tree m(
int
n)
{
if
( n
>
0 )
return
new
Tree(m(n-1),m(n-1),f(n));
else
return null
;
}
•
static int
f(
int
n)
{
int
a=0,i=n;
•
for
(; n
>
1;n=n/2 )
a += g(n).intValue();
•
for
(; i
>
1; i=i/2)
a *= h(i).intValue();
return
a;
}
•
static
Integer g(int n)
{
Integer x=
new
Integer
2(n)
;
return
new
Integer
3(x.intValue()+1)
;
}
•
static
Long h(int n)
{
return
new
Long
4(n-1)
;
}
}
// end of class Test
c ollectable
(g) =
{Integer
2}
c ollectable
(h) =
∅
c ollectable
(f
) =
{Integer
2,
Integer
3
,
Long
Bounds on Escaped Memory
escaped memory of a procedure
p
given the set of collectable objects after return from p,
collectable
(
p
),
given the upper-bound for the total memory allocation
total
(
p
) =
exp
the escaped memory upper-bound:
given the set of collectable objects after return from p,
collectable
(
p
),
given the upper-bound for the total memory allocation
total
(
p
) =
exp
the escaped memory upper-bound:
escaped
(
p
) =
exp
[
∀
c
i
∈
collectable
(
p
)
.
size
(
c
i
)
7→
0].
g
(
n
) =
size
(
Integer
2
)+
size
(
Integer
3
)
h
(
n
) =
size
(
Long
4
)
f
(
n
) = log
2
(
n
)
∗
(
size
(
Integer
2
)+
size
(
Integer
3
)+
size
(
Long
4
))
m
(
n
) =(2
n
)
∗
(
size
(
Tree
1
)+
log
2
(
n
)
∗
(
size
(
Integer
2
)+
size
(
Integer
3
)+
size
(
Long
4
)))
c ollectable
(g) =
{Integer
2}
c ollectable
(h) =
∅
c ollectable
(f
) =
{Integer
2,
Integer
3
,
Long
Bounds on Escaped Memory
escaped memory of a procedure
p
given the set of collectable objects after return from p,
collectable
(
p
),
given the upper-bound for the total memory allocation
total
(
p
) =
exp
the escaped memory upper-bound:
escaped
(
p
) =
exp
[
∀
c
i
∈
collectable
(
p
)
.
size
(
c
i
)
7→
0].
g
(
n
) =
size
(
Integer
2
)
+
size
(
Integer
3
)
h
(
n
) =
size
(
Long
4
)
f
(
n
) = log
2
(
n
)
∗
(
size
(
Integer
2
)+
size
(
Integer
3
)+
size
(
Long
4
))
m
(
n
) =(2
n
)
∗
(
size
(
Tree
1
)+
log
2
(
n
)
∗
(
size
(
Integer
2
)+
size
(
Integer
3
)+
size
(
Long
4
)))
c ollectable
(
g
) =
{
Integer
2}
given the set of collectable objects after return from p,
collectable
(
p
),
given the upper-bound for the total memory allocation
total
(
p
) =
exp
the escaped memory upper-bound:
escaped
(
p
) =
exp
[
∀
c
i
∈
collectable
(
p
)
.
size
(
c
i
)
7→
0].
ˇ
g
(
n
) =
size
(
Integer
3
)
h
(
n
) =
size
(
Long
4
)
f
(
n
) = log
2
(
n
)
∗
(
size
(
Integer
2
)+
size
(
Integer
3
)+
size
(
Long
4
))
m
(
n
) =(2
n
)
∗
(
size
(
Tree
1
)+
log
2
(
n
)
∗
(
size
(
Integer
2
)+
size
(
Integer
3
)+
size
(
Long
4
)))
c ollectable
(g) =
{Integer
2}
c ollectable
(
h
) =
∅
c ollectable
(f
) =
{Integer
2,
Integer
3
,
Long
Bounds on Escaped Memory
escaped memory of a procedure
p
given the set of collectable objects after return from p,
collectable
(
p
),
given the upper-bound for the total memory allocation
total
(
p
) =
exp
the escaped memory upper-bound:
escaped
(
p
) =
exp
[
∀
c
i
∈
collectable
(
p
)
.
size
(
c
i
)
7→
0].
ˇ
g
(
n
) =
size
(
Integer
3
)
ˇ
h
(
n
) =
size
(
Long
4
)
f
(
n
) = log
2
(
n
)
∗
(
size
(
Integer
2
)
+
size
(
Integer
3
)
+
size
(
Long
4
)
)
m
(
n
) =(2
n
)
∗
(
size
(
Tree
1
)+
log
2
(
n
)
∗
(
size
(
Integer
2
)+
size
(
Integer
3
)+
size
(
Long
4
)))
given the set of collectable objects after return from p,
collectable
(
p
),
given the upper-bound for the total memory allocation
total
(
p
) =
exp
the escaped memory upper-bound:
escaped
(
p
) =
exp
[
∀
c
i
∈
collectable
(
p
)
.
size
(
c
i
)
7→
0].
ˇ
g
(
n
) =
size
(
Integer
3
)
ˇ
h
(
n
) =
size
(
Long
4
)
ˇ
f
(
n
) =0
m
(
n
) =(2
n
)
∗
(
size
(
Tree
1
)+
log
2
(
n
)
∗
(
size
(
Integer
2
)
+
size
(
Integer
3
)
+
size
(
Long
4
)
))
c ollectable
(g) =
{Integer
2}
c ollectable
(h) =
∅
c ollectable
(f
) =
{Integer
2,
Integer
3
,
Long
Bounds on Escaped Memory
escaped memory of a procedure
p
given the set of collectable objects after return from p,
collectable
(
p
),
given the upper-bound for the total memory allocation
total
(
p
) =
exp
the escaped memory upper-bound:
escaped
(
p
) =
exp
[
∀
c
i
∈
collectable
(
p
)
.
size
(
c
i
)
7→
0].
ˇ
g
(
n
) =
size
(
Integer
3
)
ˇ
h
(
n
) =
size
(
Long
4
)
ˇ
f
(
n
) =0
ˇ
m
(
n
) =(2
n
)
∗
size
(
Tree
1
)
Build cost relations which capture the basic idea
Step 2: Inference of Live Memory Bounds
Build cost relations which capture the basic idea
peak
(
{
m
1
;
m
2
}
) =
max
(
peak
(
m
1
)
,
escaped
(
m
1
)
+
peak
(
m
2
))
Consider a rule
p
::=
g,
b1, . . . ,
bn
. Its
peak consumption
equation is
Build cost relations which capture the basic idea
peak
(
{
m
1
;
m
2
}
) =
max
(
peak
(
m
1
)
,
escaped
(
m
1
)
+
peak
(
m
2
))
Consider a rule
p
::=
g,
b1, . . . ,
bn
. Its
peak consumption
equation is
peak
(
p
) =
T
(
b
1
, . . . ,
b
n
)
, ϕ
r
where
T
is defined as follows:
peak cost relation
T
(
b
1
, . . . ,
b
n
)::=
◮
if
b
1
is a call, then
max
(
peak
(
b
1
)
,
escaped
(
b
1
)
+
T
(
b
2
, . . . ,
b
n
))
◮