001: /*
002: * Copyright (C) 1999-2004 <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</a>
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package org.mandarax.examples.family.performance;
020:
021: // import org.apache.log4j.*;
022: import java.util.*;
023: import org.mandarax.kernel.*;
024: import org.mandarax.reference.AbstractResolutionInferenceEngine;
025: import org.mandarax.reference.AdvancedKnowledgeBase;
026: import org.mandarax.reference.ResolutionInferenceEngine3;
027: import org.mandarax.util.LogicFactorySupport;
028:
029: /**
030: * Abstract stress test class used to check for OutOfMemory errors.
031: * It appears that the OutOfMemory error only occurs when logging is set to DEBUG !!
032: * (version : 3.2)
033: * @author <A href="http://www-ist.massey.ac.nz/JBDietrich" target="_top">Jens Dietrich</A>
034: * @version 3.4 <7 March 05>
035: * @since 3.2.1
036: */
037: public abstract class AbstractMemoryTest {
038: public static final String FAMILY_ROOT = "root";
039: public static final int NUMBER_OF_SONS = 50;
040: public static final int NUMBER_OF_GRANDCHILDREN_PER_SON = 3;
041:
042: /**
043: * Run the test.
044: */
045: public void test() throws Exception {
046: // disable deep level logging
047: // BasicConfigurator.configure();
048:
049: // replaceLevel.DEBUG by Level.INFO and the OutOfMemoryError will disappear
050: // Category.getRoot().setLevel(Level.INFO);
051:
052: configureLogging();
053:
054: System.out.println("Run memory profiling test " + this );
055:
056: // get kb
057: KnowledgeBase kb = createKB();
058:
059: // issue query
060: AbstractResolutionInferenceEngine ie = new ResolutionInferenceEngine3();
061: ie.setMaxNumberOfProofSteps(100000);
062: Query query = kb.getQuery("query");
063:
064: long freeMem = Runtime.getRuntime().freeMemory();
065: List values = new ArrayList();
066: long old = freeMem;
067: long minValue = -1;
068: long maxValue = 1;
069: for (int i = 0; i < 100; i++) {
070: try {
071: run(ie, query, kb, false);
072: old = freeMem;
073: freeMem = Runtime.getRuntime().freeMemory();
074: values.add(new Long(freeMem));
075: // compute average, max und min
076: if (minValue == -1)
077: minValue = freeMem;
078: if (maxValue == -1)
079: maxValue = freeMem;
080: minValue = Math.min(minValue, freeMem);
081: maxValue = Math.max(maxValue, freeMem);
082: long avg = 0;
083: for (int j = 0; j < values.size(); j++)
084: avg = avg + ((Long) values.get(j)).longValue();
085: avg = avg / values.size();
086:
087: // print report
088: this .logMemSnapshot(i, freeMem, old, minValue,
089: maxValue, avg);
090: } catch (Throwable t) {
091: t.printStackTrace();
092: }
093:
094: }
095:
096: System.out.println("Computation finished !");
097: System.exit(0);
098:
099: }
100:
101: /**
102: * Log a memory snapshot.
103: * @param i the computation step
104: * @param freeMem the free memory
105: * @param oldValue the last free memory value
106: * @param min the min value from all snapshots in this series
107: * @param max the max value from all snapshots in this series
108: * @param avgValue the average value from all snapshots in this series
109: */
110: private void logMemSnapshot(int i, long freeMem, long oldValue,
111: long minValue, long maxValue, long avgValue) {
112: // print report
113: System.out.println("run no " + i);
114: System.out.println("free memory " + freeMem);
115: System.out.println("prev free memory was " + oldValue);
116: System.out.println("min free memory was " + minValue);
117: System.out.println("max free memory was " + maxValue);
118: System.out.println("avg free memory was " + avgValue);
119: }
120:
121: /**
122: * Configure logging - logging is critical!!
123: */
124: public abstract void configureLogging();
125:
126: /**
127: * Run and time the computation.
128: */
129: private static void run(InferenceEngine ie, Query q,
130: KnowledgeBase kb, boolean logResults) {
131: try {
132: long before = System.currentTimeMillis();
133: ResultSet rs = ie.query(q, kb, InferenceEngine.ALL,
134: InferenceEngine.BUBBLE_EXCEPTIONS);
135: long after = System.currentTimeMillis();
136:
137: // count results
138: int solutions = 0;
139: while (rs.next()) {
140: solutions = solutions + 1;
141: if (logResults) {
142: System.out.print(rs.getResult(String.class, "x"));
143: System.out.print(" is brother of ");
144: System.out.println(rs.getResult(String.class, "y"));
145: }
146: }
147:
148: // report
149: System.out.println("solutions found: " + solutions);
150: System.out.println("time (in millis): " + (after - before));
151: } catch (Exception x) {
152: x.printStackTrace();
153: }
154: }
155:
156: /**
157: * Set up the knowledge base.
158: * @return the knowledge base.
159: */
160: private static KnowledgeBase createKB() {
161: LogicFactorySupport lfs = new LogicFactorySupport();
162:
163: // init predicates
164: Class[] struct = { String.class, String.class };
165: Predicate predicate_is_father = new SimplePredicate("father",
166: struct);
167: Predicate predicate_is_brother = new SimplePredicate("brother",
168: struct);
169:
170: // add knowledge - rule
171: KnowledgeBase kb = new AdvancedKnowledgeBase();
172: Rule rule = lfs.rule(lfs.prereq(predicate_is_father, lfs
173: .variable("s"), lfs.variable("f")), lfs.prereq(
174: predicate_is_father, lfs.variable("t"), lfs
175: .variable("f")), lfs.prereq(
176: org.mandarax.lib.text.StringArithmetic.NOT_EQUAL, lfs
177: .variable("s"), lfs.variable("t")), lfs.fact(
178: predicate_is_brother, lfs.variable("s"), lfs
179: .variable("t")));
180: kb.add(rule);
181:
182: // add facts for family tree
183: for (int i = 0; i < NUMBER_OF_SONS; i++) {
184: kb
185: .add(lfs.fact(predicate_is_father, lfs.cons("" + i,
186: String.class), lfs.cons(FAMILY_ROOT,
187: String.class)));
188: for (int j = 0; j < NUMBER_OF_GRANDCHILDREN_PER_SON; j++) {
189: kb.add(lfs.fact(predicate_is_father, lfs.cons("" + i
190: + "." + j, String.class), lfs.cons("" + i,
191: String.class)));
192: }
193: }
194: // add query
195: kb.addQuery(lfs.query(lfs.fact(predicate_is_brother, lfs
196: .variable("x", String.class), lfs.variable("y",
197: String.class)), "query"));
198:
199: // return
200: return kb;
201: }
202: }
|