/*
* Copyright (C) 2014 me
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package nars.perf;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.AtomicDouble;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import nars.storage.Memory;
import nars.NAR;
import nars.config.Parameters;
import nars.config.Plugins;
import nars.entity.BudgetValue;
import nars.entity.Item;
import nars.storage.Bag;
import nars.storage.LevelBag;
/**
*
* @author me
*/
public class BagPerf {
int repeats = 8;
int warmups = 1;
final static AtomicDouble forgetRate = (new NAR(new Plugins()).param).conceptForgetDurations;
int randomAccesses;
double insertRatio = 0.9;
public float totalPriority, totalMass, totalMinItemsPerLevel, totalMaxItemsPerLevel;
public void testBag(final boolean arraylist, final int levels, final int capacity, final AtomicDouble forgetRate) {
totalPriority = 0;
totalMass = 0;
totalMaxItemsPerLevel = totalMinItemsPerLevel = 0;
Performance p = new Performance((arraylist ? "DequeArray" : "LinkedList")+","+levels+","+ capacity, repeats, warmups) {
@Override public void init() { }
@Override
public void run(boolean warmup) {
LevelBag<NullItem,CharSequence> b = new LevelBag(levels, capacity) {
// @Override
// protected ArrayDeque<NullItem> newLevel() {
// //if (arraylist)
// return super.newLevel();
// //return new LinkedList<>();
// }
};
randomBagIO(b, randomAccesses, insertRatio);
if (!warmup) {
totalPriority += b.getAveragePriority();
totalMass += b.getMass();
totalMinItemsPerLevel += b.getMinItemsPerLevel();
totalMaxItemsPerLevel += b.getMaxItemsPerLevel();
}
}
}.printCSV(true);
//items per level min
//items per lvel max
//avg prioirty
//avg norm mass
//System.out.print((totalMinItemsPerLevel/p.repeats) + ",");
System.out.print((totalMaxItemsPerLevel/p.repeats) + ",");
System.out.print(totalPriority/p.repeats + ",");
System.out.print(totalMass/repeats/levels + ",");
System.out.println();
}
public static int itemID = 0;
/** Empty Item implementation useful for testing */
public static class NullItem extends Item.StringKeyItem {
public String key;
public NullItem() {
this(Memory.randomNumber.nextFloat() * (1.0f - Parameters.TRUTH_EPSILON));
}
public NullItem(float priority) {
super(new BudgetValue(priority, priority, priority));
this.key = "" + (itemID++);
}
@Override
public CharSequence name() {
return key;
}
}
public static void randomBagIO(Bag<NullItem,CharSequence> b, int accesses, double insertProportion) {
for (int i = 0; i < accesses; i++) {
if (Memory.randomNumber.nextFloat() > insertProportion) {
//remove
b.takeNext();
}
else {
//insert
b.putIn(new NullItem());
}
}
}
public static void iterate(Bag<NullItem,CharSequence> b) {
Iterator<NullItem> i = b.iterator();
int count = 0;
while (i.hasNext()) {
i.next();
count++;
}
if (count != b.size()) {
System.err.println("Error itrating " + b.getClass() + " " + b.size() + " != " + count);
}
}
public interface BagBuilder<E extends Item<K>,K> {
public Bag<E,K> newBag();
}
//final boolean first, final int levels, final int levelCapacity,
public static double getTime(String label, BagBuilder b, final int iterations, final int randomAccesses, final float insertRatio, int repeats, int warmups) {
Memory.resetStatic();
Performance p = new Performance(label, repeats, warmups) {
@Override public void init() { }
@Override
public void run(boolean warmup) {
Bag bag = b.newBag();
randomBagIO(bag, randomAccesses, insertRatio);
for (int i = 0; i < iterations; i++)
iterate(bag);
}
};//.printCSV(false);
//System.out.println();
return p.getCycleTimeMS();
}
public BagPerf() {
for (int capacity = 8; capacity < 40000; capacity*=capacity) {
randomAccesses = capacity*64;
for (int i = 5; i < 200; i+=5) {
testBag(false, i, capacity, forgetRate);
testBag(true, i, capacity, forgetRate);
}
}
}
public static Map<Bag,Double> compare(final int iterations, final int randomAccesses, final float insertRatio, int repeats, int warmups, final Bag... B) {
Map<Bag,Double> t = new LinkedHashMap();
for (Bag X : B) {
X.clear();
t.put(X, getTime(X.toString(), new BagBuilder() {
@Override public Bag newBag() { return X; }
}, iterations, randomAccesses, insertRatio, repeats, warmups));
}
return t;
}
public static void printCSVLine(PrintStream out, String... s) {
printCSVLine(out, Lists.newArrayList(s));
}
public static void printCSVLine(PrintStream out, List<String> o) {
StringJoiner line = new StringJoiner(", ", "", "");
for (String x : o)
line.add(x);
out.println(line.toString());
}
public static void main(String[] args) {
int itemsPerLevel = 10;
int repeats = 10;
int warmups = 1;
int iterationsPerItem = 0;
int accessesPerItem = 8;
boolean printedHeader = false;
for (float insertRatio = 0.1f; insertRatio <= 1.0f; insertRatio += 0.1f) {
for (int levels = 1; levels <= 10; levels += 1) {
final int items = levels*itemsPerLevel;
final int iterations = iterationsPerItem * items;
int randomAccesses = accessesPerItem * items;
Bag[] bags = new Bag[] {
new LevelBag(levels, items)
};
Map<Bag, Double> t = BagPerf.compare(
iterations, randomAccesses, insertRatio, repeats, warmups,
bags
);
/*System.out.print(Arrays.toString(new Object[] { "(x" + repeats + ")", "items", items, "inserts:removals", insertRatio, "accesses", randomAccesses, "nexts", iterations }));
System.out.print(" ");
for (Map.Entry<Bag, Double> e : t.entrySet()) {
System.out.print(e.getKey() + "," + e.getValue() + ", ");
}*/
if (!printedHeader) {
List<String> ls = Lists.newArrayList("items", "io_ratio", "accesses", "nexts");
for (Map.Entry<Bag, Double> e : t.entrySet())
ls.add(e.getKey().toString());
printCSVLine(System.out, ls );
printedHeader = true;
}
{
List<String> ls = Lists.newArrayList(items+"", insertRatio+"", randomAccesses+"", iterations+"");
for (Map.Entry<Bag, Double> e : t.entrySet())
ls.add(e.getValue().toString());
printCSVLine(System.out, ls );
}
}
}
}
}