Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
N
nofib
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Glasgow Haskell Compiler
nofib
Commits
7a1394b6
Commit
7a1394b6
authored
5 years ago
by
Ben Gamari
Browse files
Options
Downloads
Patches
Plain Diff
gc/gc_bench: De-tabify
parent
a67e384e
No related branches found
Branches containing commit
No related tags found
1 merge request
!30
Normalise benchmarks
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
gc/gc_bench/Main.hs
+164
-164
164 additions, 164 deletions
gc/gc_bench/Main.hs
with
164 additions
and
164 deletions
gc/gc_bench/Main.hs
+
164
−
164
View file @
7a1394b6
...
...
@@ -3,122 +3,122 @@
// of Post Communications.
// It was modified by Hans Boehm of Silicon Graphics.
//
//
This is no substitute for real applications. No actual application
//
is likely to behave in exactly this way. However, this benchmark was
//
designed to be more representative of real applications than other
//
Java GC benchmarks of which we are aware.
//
It attempts to model those properties of allocation requests that
//
are important to current GC techniques.
//
It is designed to be used either to obtain a single overall performance
//
number, or to give a more detailed estimate of how collector
//
performance varies with object lifetimes. It prints the time
//
required to allocate and collect balanced binary trees of various
//
sizes. Smaller trees result in shorter object lifetimes. Each cycle
//
allocates roughly the same amount of memory.
//
Two data structures are kept around during the entire process, so
//
that the measured performance is representative of applications
//
that maintain some live in-memory data. One of these is a tree
//
containing many pointers. The other is a large array containing
//
double precision floating point numbers. Both should be of comparable
//
size.
//
This is no substitute for real applications. No actual application
//
is likely to behave in exactly this way. However, this benchmark was
//
designed to be more representative of real applications than other
//
Java GC benchmarks of which we are aware.
//
It attempts to model those properties of allocation requests that
//
are important to current GC techniques.
//
It is designed to be used either to obtain a single overall performance
//
number, or to give a more detailed estimate of how collector
//
performance varies with object lifetimes. It prints the time
//
required to allocate and collect balanced binary trees of various
//
sizes. Smaller trees result in shorter object lifetimes. Each cycle
//
allocates roughly the same amount of memory.
//
Two data structures are kept around during the entire process, so
//
that the measured performance is representative of applications
//
that maintain some live in-memory data. One of these is a tree
//
containing many pointers. The other is a large array containing
//
double precision floating point numbers. Both should be of comparable
//
size.
//
//
The results are only really meaningful together with a specification
//
of how much memory was used. It is possible to trade memory for
//
better time performance. This benchmark should be run in a 32 MB
//
heap, though we don't currently know how to enforce that uniformly.
//
The results are only really meaningful together with a specification
//
of how much memory was used. It is possible to trade memory for
//
better time performance. This benchmark should be run in a 32 MB
//
heap, though we don't currently know how to enforce that uniformly.
//
//
Unlike the original Ellis and Kovac benchmark, we do not attempt
//
measure pause times. This facility should eventually be added back
//
in. There are several reasons for omitting it for now. The original
//
implementation depended on assumptions about the thread scheduler
//
that don't hold uniformly. The results really measure both the
//
scheduler and GC. Pause time measurements tend to not fit well with
//
current benchmark suites. As far as we know, none of the current
//
commercial Java implementations seriously attempt to minimize GC pause
//
times.
//
Unlike the original Ellis and Kovac benchmark, we do not attempt
//
measure pause times. This facility should eventually be added back
//
in. There are several reasons for omitting it for now. The original
//
implementation depended on assumptions about the thread scheduler
//
that don't hold uniformly. The results really measure both the
//
scheduler and GC. Pause time measurements tend to not fit well with
//
current benchmark suites. As far as we know, none of the current
//
commercial Java implementations seriously attempt to minimize GC pause
//
times.
//
//
Known deficiencies:
//
- No way to check on memory use
//
- No cyclic data structures
//
- No attempt to measure variation with object size
//
- Results are sensitive to locking cost, but we dont
//
check for proper locking
//
Known deficiencies:
//
- No way to check on memory use
//
- No cyclic data structures
//
- No attempt to measure variation with object size
//
- Results are sensitive to locking cost, but we dont
//
check for proper locking
class Node {
Node left, right;
int i, j;
Node(Node l, Node r) { left = l; right = r; }
Node() { }
Node left, right;
int i, j;
Node(Node l, Node r) { left = l; right = r; }
Node() { }
}
public class GCBench {
public static final int kStretchTreeDepth = 18;
// about 16Mb
public static final int kLongLivedTreeDepth = 16; // about 4Mb
public static final int kArraySize = 500000; // about 4Mb
public static final int kMinTreeDepth = 4;
public static final int kMaxTreeDepth = 16;
public static final int kStretchTreeDepth = 18;
// about 16Mb
public static final int kLongLivedTreeDepth = 16; // about 4Mb
public static final int kArraySize = 500000; // about 4Mb
public static final int kMinTreeDepth = 4;
public static final int kMaxTreeDepth = 16;
// Nodes used by a tree of a given size
static int TreeSize(int i) {
return ((1 << (i + 1)) - 1);
}
// Nodes used by a tree of a given size
static int TreeSize(int i) {
return ((1 << (i + 1)) - 1);
}
// Number of iterations to use for a given tree depth
static int NumIters(int i) {
// Number of iterations to use for a given tree depth
static int NumIters(int i) {
return 2 * TreeSize(kStretchTreeDepth) / TreeSize(i);
}
// Build tree top down, assigning to older objects.
static void Populate(int iDepth, Node thisNode) {
if (iDepth<=0) {
return;
} else {
iDepth--;
thisNode.left = new Node();
thisNode.right = new Node();
Populate (iDepth, thisNode.left);
Populate (iDepth, thisNode.right);
}
}
// Build tree bottom-up
static Node MakeTree(int iDepth) {
if (iDepth<=0) {
return new Node();
} else {
return new Node(MakeTree(iDepth-1),
MakeTree(iDepth-1));
}
}
static void PrintDiagnostics() {
long lFreeMemory = Runtime.getRuntime().freeMemory();
long lTotalMemory = Runtime.getRuntime().totalMemory();
System.out.print(" Total memory available="
+ lTotalMemory + " bytes");
System.out.println(" Free memory=" + lFreeMemory + " bytes");
}
static void TimeConstruction(int depth) {
Node root;
long tStart, tFinish;
int
iNumIters = NumIters(depth);
Node
tempTree;
System.out.println("Creating " + iNumIters +
" trees of depth " + depth);
tStart = System.currentTimeMillis();
for (int i = 0; i < iNumIters; ++i) {
tempTree = new Node();
Populate(depth, tempTree);
tempTree = null;
}
tFinish = System.currentTimeMillis();
System.out.println("\tTop down construction took "
+ (tFinish - tStart) + "msecs");
tStart = System.currentTimeMillis();
// Build tree top down, assigning to older objects.
static void Populate(int iDepth, Node thisNode) {
if (iDepth<=0) {
return;
} else {
iDepth--;
thisNode.left = new Node();
thisNode.right = new Node();
Populate (iDepth, thisNode.left);
Populate (iDepth, thisNode.right);
}
}
// Build tree bottom-up
static Node MakeTree(int iDepth) {
if (iDepth<=0) {
return new Node();
} else {
return new Node(MakeTree(iDepth-1),
MakeTree(iDepth-1));
}
}
static void PrintDiagnostics() {
long lFreeMemory = Runtime.getRuntime().freeMemory();
long lTotalMemory = Runtime.getRuntime().totalMemory();
System.out.print(" Total memory available="
+ lTotalMemory + " bytes");
System.out.println(" Free memory=" + lFreeMemory + " bytes");
}
static void TimeConstruction(int depth) {
Node root;
long tStart, tFinish;
int
iNumIters = NumIters(depth);
Node
tempTree;
System.out.println("Creating " + iNumIters +
" trees of depth " + depth);
tStart = System.currentTimeMillis();
for (int i = 0; i < iNumIters; ++i) {
tempTree = new Node();
Populate(depth, tempTree);
tempTree = null;
}
tFinish = System.currentTimeMillis();
System.out.println("\tTop down construction took "
+ (tFinish - tStart) + "msecs");
tStart = System.currentTimeMillis();
for (int i = 0; i < iNumIters; ++i) {
tempTree = MakeTree(depth);
tempTree = null;
...
...
@@ -126,60 +126,60 @@ public class GCBench {
tFinish = System.currentTimeMillis();
System.out.println("\tBottom up construction took "
+ (tFinish - tStart) + "msecs");
}
public static void main(String args[]) {
Node
root;
Node
longLivedTree;
Node
tempTree;
long
tStart, tFinish;
long
tElapsed;
System.out.println("Garbage Collector Test");
System.out.println(
" Stretching memory with a binary tree of depth "
+ kStretchTreeDepth);
PrintDiagnostics();
tStart = System.currentTimeMillis();
// Stretch the memory space quickly
tempTree = MakeTree(kStretchTreeDepth);
tempTree = null;
// Create a long lived object
System.out.println(
" Creating a long-lived binary tree of depth " +
kLongLivedTreeDepth);
longLivedTree = new Node();
Populate(kLongLivedTreeDepth, longLivedTree);
// Create long-lived array, filling half of it
System.out.println(
}
public static void main(String args[]) {
Node
root;
Node
longLivedTree;
Node
tempTree;
long
tStart, tFinish;
long
tElapsed;
System.out.println("Garbage Collector Test");
System.out.println(
" Stretching memory with a binary tree of depth "
+ kStretchTreeDepth);
PrintDiagnostics();
tStart = System.currentTimeMillis();
// Stretch the memory space quickly
tempTree = MakeTree(kStretchTreeDepth);
tempTree = null;
// Create a long lived object
System.out.println(
" Creating a long-lived binary tree of depth " +
kLongLivedTreeDepth);
longLivedTree = new Node();
Populate(kLongLivedTreeDepth, longLivedTree);
// Create long-lived array, filling half of it
System.out.println(
" Creating a long-lived array of "
+ kArraySize + " doubles");
double array[] = new double[kArraySize];
for (int i = 0; i < kArraySize/2; ++i) {
array[i] = 1.0/i;
}
PrintDiagnostics();
for (int d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2) {
TimeConstruction(d);
}
if (longLivedTree == null || array[1000] != 1.0/1000)
System.out.println("Failed");
// fake reference to LongLivedTree
// and array
// to keep them from being optimized away
tFinish = System.currentTimeMillis();
tElapsed = tFinish-tStart;
PrintDiagnostics();
System.out.println("Completed in " + tElapsed + "ms.");
}
+ kArraySize + " doubles");
double array[] = new double[kArraySize];
for (int i = 0; i < kArraySize/2; ++i) {
array[i] = 1.0/i;
}
PrintDiagnostics();
for (int d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2) {
TimeConstruction(d);
}
if (longLivedTree == null || array[1000] != 1.0/1000)
System.out.println("Failed");
// fake reference to LongLivedTree
// and array
// to keep them from being optimized away
tFinish = System.currentTimeMillis();
tElapsed = tFinish-tStart;
PrintDiagnostics();
System.out.println("Completed in " + tElapsed + "ms.");
}
} // class JavaGC
-}
...
...
@@ -187,8 +187,8 @@ import Text.Printf
import
System.CPUTime
import
Data.IORef
import
Data.Array.IO
import
System.Time
(
ClockTime
(
..
)
)
import
Control.Monad
(
replicateM_
)
import
System.Time
(
ClockTime
(
..
)
)
import
Control.Monad
(
replicateM_
)
import
System.IO
import
System.Environment
...
...
@@ -211,8 +211,8 @@ data Tree = Node { left, right :: Tree, i :: Int } | Empty
makeTree
0
=
Node
{
left
=
Empty
,
right
=
Empty
,
i
=
0
}
makeTree
iDepth
=
Node
{
left
=
makeTree
(
iDepth
-
1
),
right
=
makeTree
(
iDepth
-
1
),
i
=
0
}
right
=
makeTree
(
iDepth
-
1
),
i
=
0
}
data
MutTree
=
MutNode
(
IORef
MutTree
)
(
IORef
MutTree
)
Int
|
MutEmpty
...
...
@@ -239,16 +239,16 @@ timeConstruction max depth = do
-- printf "Creating %d trees of depth %d\n" iNumIters depth
tStart
<-
getCPUTime
replicateM_
iNumIters
$
do
n
<-
newMutNode
depth
;
populate
depth
n
;
touch
n
n
<-
newMutNode
depth
;
populate
depth
n
;
touch
n
tFinish
<-
getCPUTime
-- printf "\tTop down construction took "
-- ptimediff stdout tStart tFinish
-- printf "\n"
tStart
<-
getCPUTime
replicateM_
iNumIters
$
do
let
tempTree
=
makeTree
depth
deepSeq
tempTree
(
return
()
)
touch
tempTree
let
tempTree
=
makeTree
depth
deepSeq
tempTree
(
return
()
)
touch
tempTree
tFinish
<-
getCPUTime
-- printf "\tBottom-up construction took "
-- ptimediff stdout tStart tFinish
...
...
@@ -281,7 +281,7 @@ main = do
array
<-
newArray
(
1
,
kArraySize
)
0.0
let
_
=
array
::
IOArray
Int
Double
sequence_
[
writeArray
array
i
(
1.0
/
fromIntegral
i
)
|
i
<-
[
1
..
kArraySize
`
quot
`
2
]
]
|
i
<-
[
1
..
kArraySize
`
quot
`
2
]
]
sequence_
[
timeConstruction
kMaxTreeDepth
d
|
d
<-
[
kMinTreeDepth
,
kMinTreeDepth
+
2
..
kMaxTreeDepth
]
]
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment