From 266fbedbd31b19cf7763bf9e7eeabf3252051dcd Mon Sep 17 00:00:00 2001 From: Adam Warski Date: Thu, 20 Nov 2008 13:09:44 +0000 Subject: [PATCH] Performance tests git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@15601 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- .../envers/test/AbstractEntityTest.java | 43 ++++- .../performance/AbstractPerformanceTest.java | 94 +++++++---- .../performance/ComplexInsertPerformance.java | 105 ++++++++++++ .../InsertsOneTransactionPerformance.java | 59 +++++++ .../test/performance/InsertsPerformance.java | 36 +--- .../test/performance/UpdatesPerformance.java | 54 ++---- .../performance/complex/ChildEntity1.java | 113 +++++++++++++ .../performance/complex/ChildEntity2.java | 102 +++++++++++ .../test/performance/complex/RootEntity.java | 159 ++++++++++++++++++ .../src/test/resources/hibernate.test.cfg.xml | 10 +- 10 files changed, 665 insertions(+), 110 deletions(-) create mode 100644 envers/src/test/java/org/hibernate/envers/test/performance/ComplexInsertPerformance.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/performance/InsertsOneTransactionPerformance.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/performance/complex/ChildEntity1.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/performance/complex/ChildEntity2.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/performance/complex/RootEntity.java diff --git a/envers/src/test/java/org/hibernate/envers/test/AbstractEntityTest.java b/envers/src/test/java/org/hibernate/envers/test/AbstractEntityTest.java index 211725dc05..5e0fb645ba 100644 --- a/envers/src/test/java/org/hibernate/envers/test/AbstractEntityTest.java +++ b/envers/src/test/java/org/hibernate/envers/test/AbstractEntityTest.java @@ -29,10 +29,13 @@ import javax.persistence.EntityManagerFactory; import org.hibernate.envers.AuditReader; import org.hibernate.envers.AuditReaderFactory; +import org.hibernate.envers.event.AuditEventListener; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; +import org.testng.annotations.AfterClass; import org.hibernate.ejb.Ejb3Configuration; +import org.hibernate.event.*; /** * @author Adam Warski (adam at warski dot org) @@ -42,22 +45,50 @@ public abstract class AbstractEntityTest { private EntityManager entityManager; private AuditReader auditReader; private Ejb3Configuration cfg; + private boolean audited; public abstract void configure(Ejb3Configuration cfg); - @BeforeMethod - public void newEntityManager() { + protected void initListeners() { + AuditEventListener listener = new AuditEventListener(); + cfg.getEventListeners().setPostInsertEventListeners(new PostInsertEventListener[] { listener }); + cfg.getEventListeners().setPostUpdateEventListeners(new PostUpdateEventListener[] { listener }); + cfg.getEventListeners().setPostDeleteEventListeners(new PostDeleteEventListener[] { listener }); + cfg.getEventListeners().setPreCollectionUpdateEventListeners(new PreCollectionUpdateEventListener[] { listener }); + cfg.getEventListeners().setPreCollectionRemoveEventListeners(new PreCollectionRemoveEventListener[] { listener }); + cfg.getEventListeners().setPostCollectionRecreateEventListeners(new PostCollectionRecreateEventListener[] { listener }); + } + + private void closeEntityManager() { if (entityManager != null) { entityManager.close(); + entityManager = null; } + } + + @BeforeMethod + public void newEntityManager() { + closeEntityManager(); entityManager = emf.createEntityManager(); - auditReader = AuditReaderFactory.get(entityManager); + + if (audited) { + auditReader = AuditReaderFactory.get(entityManager); + } } @BeforeClass public void init() throws IOException { + init(true); + } + + protected void init(boolean audited) throws IOException { + this.audited = audited; + cfg = new Ejb3Configuration(); + if (audited) { + initListeners(); + } cfg.configure("hibernate.test.cfg.xml"); configure(cfg); emf = cfg.buildEntityManagerFactory(); @@ -65,6 +96,12 @@ public abstract class AbstractEntityTest { newEntityManager(); } + @AfterClass + public void close() { + closeEntityManager(); + emf.close(); + } + public EntityManager getEntityManager() { return entityManager; } diff --git a/envers/src/test/java/org/hibernate/envers/test/performance/AbstractPerformanceTest.java b/envers/src/test/java/org/hibernate/envers/test/performance/AbstractPerformanceTest.java index 5e7e939159..8c493ccfc9 100644 --- a/envers/src/test/java/org/hibernate/envers/test/performance/AbstractPerformanceTest.java +++ b/envers/src/test/java/org/hibernate/envers/test/performance/AbstractPerformanceTest.java @@ -24,7 +24,10 @@ package org.hibernate.envers.test.performance; import org.hibernate.envers.test.AbstractEntityTest; -import org.hibernate.envers.tools.Pair; + +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; /** * @author Adam Warski (adam at warski dot org) @@ -34,49 +37,72 @@ public abstract class AbstractPerformanceTest extends AbstractEntityTest { return (milliseconds/1000) + "." + (milliseconds%1000); } - protected long measureTime(Runnable r) { - long start = System.currentTimeMillis(); - r.run(); - return System.currentTimeMillis() - start; + protected abstract void doTest(); + + private void printResults(long unaudited, long audited) { + System.out.println("Unaudited: " + getSecondsString(unaudited)); + System.out.println(" Audited: " + getSecondsString(audited)); + System.out.println(" Delta: " + getSecondsString(audited-unaudited)); + System.out.println(" Factor: " + (double)audited/unaudited); } - protected abstract Pair doTest(); + private long startTime; + private long runTotal; - protected abstract String getName(); - - private long totalUnversioned; - private long totalVersioned; - - private void printResults(long unversioned, long versioned) { - System.out.println("Unversioned: " + getSecondsString(unversioned)); - System.out.println(" Versioned: " + getSecondsString(versioned)); - System.out.println(" Delta: " + getSecondsString(versioned-unversioned)); - System.out.println(" Factor: " + (double)versioned/unversioned); + protected void start() { + startTime = System.currentTimeMillis(); } - private void test(boolean count) { - Pair result = doTest(); - long unversioned = result.getFirst(); - long versioned = result.getSecond(); - - totalUnversioned += unversioned; - totalVersioned += versioned; - - printResults(unversioned, versioned); + protected void stop() { + long stopTime = System.currentTimeMillis(); + runTotal += stopTime - startTime; } - public void run(int numberOfRuns) { + protected void reset() { + runTotal = 0; + } + + public long run(int numberOfRuns, List results) { + long total = 0; for (int i=0; i<=numberOfRuns; i++) { - System.out.println(""); - System.out.println(getName() + " TEST, RUN " + i); - test(i != 0); + System.out.println(); + System.out.println("RUN " + i); + reset(); + doTest(); + results.add(runTotal); + total += runTotal; + + newEntityManager(); + + /*System.gc(); + System.gc(); + System.gc(); + System.out.println(Runtime.getRuntime().freeMemory() + ", " + Runtime.getRuntime().totalMemory() + ", " + + (Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory()));*/ } - totalUnversioned /= numberOfRuns; - totalVersioned /= numberOfRuns; + return total; + } - System.out.println(""); - System.out.println(getName() + " TEST, AVERAGE"); - printResults(totalUnversioned, totalVersioned); + public void test(int numberOfRuns) throws IOException { + List unauditedRuns = new ArrayList(); + List auditedRuns = new ArrayList(); + + init(true); + long audited = run(numberOfRuns, auditedRuns); + close(); + + init(false); + long unaudited = run(numberOfRuns, unauditedRuns); + close(); + + for (int i=0; i<=numberOfRuns; i++) { + System.out.println("RUN " + i); + printResults(unauditedRuns.get(i), auditedRuns.get(i)); + System.out.println(); + } + + System.out.println("TOTAL"); + printResults(unaudited, audited); } } diff --git a/envers/src/test/java/org/hibernate/envers/test/performance/ComplexInsertPerformance.java b/envers/src/test/java/org/hibernate/envers/test/performance/ComplexInsertPerformance.java new file mode 100644 index 0000000000..8fe0435060 --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/performance/ComplexInsertPerformance.java @@ -0,0 +1,105 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.envers.test.performance; + +import java.io.IOException; +import java.util.Date; +import java.util.HashSet; +import javax.persistence.EntityManager; + +import org.hibernate.envers.test.performance.complex.RootEntity; +import org.hibernate.envers.test.performance.complex.ChildEntity2; +import org.hibernate.envers.test.performance.complex.ChildEntity1; + +import org.hibernate.ejb.Ejb3Configuration; + +/** + * @author Adam Warski (adam at warski dot org) + */ +public class ComplexInsertPerformance extends AbstractPerformanceTest { + public void configure(Ejb3Configuration cfg) { + cfg.addAnnotatedClass(RootEntity.class); + cfg.addAnnotatedClass(ChildEntity1.class); + cfg.addAnnotatedClass(ChildEntity2.class); + } + + private final static int NUMBER_INSERTS = 100; + + private long idCounter = 0; + + private ChildEntity2 createChildEntity2() { + ChildEntity2 ce = new ChildEntity2(); + ce.setId(idCounter++); + ce.setNumber(12345678); + ce.setData("some data, not really meaningful"); + ce.setStrings(new HashSet()); + ce.getStrings().add("aaa"); + ce.getStrings().add("bbb"); + ce.getStrings().add("ccc"); + + return ce; + } + + private ChildEntity1 createChildEntity1() { + ChildEntity1 ce = new ChildEntity1(); + ce.setId(idCounter++); + ce.setData1("xxx"); + ce.setData2("yyy"); + ce.setChild1(createChildEntity2()); + ce.setChild2(createChildEntity2()); + + return ce; + } + + protected void doTest() { + for (int i=0; i doTest() { - long unversioned = measureTime(new Runnable() { public void run() { insertUnversioned(); } }); - long versioned = measureTime(new Runnable() { public void run() { insertVersioned(); } }); - - return Pair.make(unversioned, versioned); - } - - protected String getName() { - return "INSERTS"; - } - public static void main(String[] args) throws IOException { InsertsPerformance insertsPerformance = new InsertsPerformance(); - insertsPerformance.init(); - insertsPerformance.run(10); + insertsPerformance.test(3); } } diff --git a/envers/src/test/java/org/hibernate/envers/test/performance/UpdatesPerformance.java b/envers/src/test/java/org/hibernate/envers/test/performance/UpdatesPerformance.java index 97036a639a..eafeb4afc8 100644 --- a/envers/src/test/java/org/hibernate/envers/test/performance/UpdatesPerformance.java +++ b/envers/src/test/java/org/hibernate/envers/test/performance/UpdatesPerformance.java @@ -30,9 +30,6 @@ import java.util.Random; import javax.persistence.EntityManager; import org.hibernate.envers.test.entities.StrTestEntity; -import org.hibernate.envers.test.entities.UnversionedStrTestEntity; -import org.hibernate.envers.tools.Pair; - import org.hibernate.ejb.Ejb3Configuration; /** @@ -41,71 +38,46 @@ import org.hibernate.ejb.Ejb3Configuration; public class UpdatesPerformance extends AbstractPerformanceTest { public void configure(Ejb3Configuration cfg) { cfg.addAnnotatedClass(StrTestEntity.class); - cfg.addAnnotatedClass(UnversionedStrTestEntity.class); } - private final static int NUMBER_UPDATES = 1000; + private final static int NUMBER_UPDATES = 500; private final static int NUMBER_ENTITIES = 10; private Random random = new Random(); - private List unversioned_ids = new ArrayList(); - private List versioned_ids = new ArrayList(); + private List ids = new ArrayList(); - public void setup() { + private void setup() { EntityManager entityManager = getEntityManager(); entityManager.getTransaction().begin(); - for (int i=0; i doTest() { - long unversioned = measureTime(new Runnable() { public void run() { updateUnversioned(); } }); - long versioned = measureTime(new Runnable() { public void run() { updateVersioned(); } }); - - return Pair.make(unversioned, versioned); - } - - protected String getName() { - return "UPDATES"; - } - public static void main(String[] args) throws IOException { UpdatesPerformance updatesPerformance = new UpdatesPerformance(); - updatesPerformance.init(); - updatesPerformance.setup(); - updatesPerformance.run(10); + updatesPerformance.test(3); } } \ No newline at end of file diff --git a/envers/src/test/java/org/hibernate/envers/test/performance/complex/ChildEntity1.java b/envers/src/test/java/org/hibernate/envers/test/performance/complex/ChildEntity1.java new file mode 100644 index 0000000000..9a03b3c692 --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/performance/complex/ChildEntity1.java @@ -0,0 +1,113 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.envers.test.performance.complex; + +import org.hibernate.envers.Audited; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.CascadeType; + +/** + * @author Adam Warski (adam at warski dot org) + */ +@Entity +@Audited +public class ChildEntity1 { + @Id + private Long id; + + @ManyToOne(cascade = CascadeType.ALL) + private ChildEntity2 child1; + + @ManyToOne(cascade = CascadeType.ALL) + private ChildEntity2 child2; + + private String data1; + + private String data2; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public ChildEntity2 getChild1() { + return child1; + } + + public void setChild1(ChildEntity2 child1) { + this.child1 = child1; + } + + public ChildEntity2 getChild2() { + return child2; + } + + public void setChild2(ChildEntity2 child2) { + this.child2 = child2; + } + + public String getData1() { + return data1; + } + + public void setData1(String data1) { + this.data1 = data1; + } + + public String getData2() { + return data2; + } + + public void setData2(String data2) { + this.data2 = data2; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ChildEntity1)) return false; + + ChildEntity1 that = (ChildEntity1) o; + + if (data1 != null ? !data1.equals(that.data1) : that.data1 != null) return false; + if (data2 != null ? !data2.equals(that.data2) : that.data2 != null) return false; + if (id != null ? !id.equals(that.id) : that.id != null) return false; + + return true; + } + + public int hashCode() { + int result; + result = (id != null ? id.hashCode() : 0); + result = 31 * result + (data1 != null ? data1.hashCode() : 0); + result = 31 * result + (data2 != null ? data2.hashCode() : 0); + return result; + } +} diff --git a/envers/src/test/java/org/hibernate/envers/test/performance/complex/ChildEntity2.java b/envers/src/test/java/org/hibernate/envers/test/performance/complex/ChildEntity2.java new file mode 100644 index 0000000000..37321d680f --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/performance/complex/ChildEntity2.java @@ -0,0 +1,102 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.envers.test.performance.complex; + +import org.hibernate.envers.Audited; +import org.hibernate.annotations.CollectionOfElements; + +import javax.persistence.Entity; +import javax.persistence.Id; +import java.util.Set; + +/** + * @author Adam Warski (adam at warski dot org) + */ +@Entity +@Audited +public class ChildEntity2 { + @Id + private Long id; + + private String data; + + private Integer number; + + @CollectionOfElements + private Set strings; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + public Integer getNumber() { + return number; + } + + public void setNumber(Integer number) { + this.number = number; + } + + public Set getStrings() { + return strings; + } + + public void setStrings(Set strings) { + this.strings = strings; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ChildEntity2)) return false; + + ChildEntity2 that = (ChildEntity2) o; + + if (data != null ? !data.equals(that.data) : that.data != null) return false; + if (id != null ? !id.equals(that.id) : that.id != null) return false; + if (number != null ? !number.equals(that.number) : that.number != null) return false; + + return true; + } + + public int hashCode() { + int result; + result = (id != null ? id.hashCode() : 0); + result = 31 * result + (data != null ? data.hashCode() : 0); + result = 31 * result + (number != null ? number.hashCode() : 0); + return result; + } +} \ No newline at end of file diff --git a/envers/src/test/java/org/hibernate/envers/test/performance/complex/RootEntity.java b/envers/src/test/java/org/hibernate/envers/test/performance/complex/RootEntity.java new file mode 100644 index 0000000000..38d520917e --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/performance/complex/RootEntity.java @@ -0,0 +1,159 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Middleware LLC. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ + +package org.hibernate.envers.test.performance.complex; + +import org.hibernate.envers.Audited; + +import javax.persistence.*; +import java.util.Date; + +/** + * @author Adam Warski (adam at warski dot org) + */ +@Entity +@Audited +public class RootEntity { + @Id + private Long id; + + private String data1; + + private String data2; + + private Integer number1; + + private Integer number2; + + @Temporal(TemporalType.TIMESTAMP) + private Date date1; + + @ManyToOne(cascade = CascadeType.ALL) + private ChildEntity1 child1; + + @ManyToOne(cascade = CascadeType.ALL) + private ChildEntity1 child2; + + @ManyToOne(cascade = CascadeType.ALL) + private ChildEntity1 child3; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getData1() { + return data1; + } + + public void setData1(String data1) { + this.data1 = data1; + } + + public String getData2() { + return data2; + } + + public void setData2(String data2) { + this.data2 = data2; + } + + public Integer getNumber1() { + return number1; + } + + public void setNumber1(Integer number1) { + this.number1 = number1; + } + + public Integer getNumber2() { + return number2; + } + + public void setNumber2(Integer number2) { + this.number2 = number2; + } + + public Date getDate1() { + return date1; + } + + public void setDate1(Date date1) { + this.date1 = date1; + } + + public ChildEntity1 getChild1() { + return child1; + } + + public void setChild1(ChildEntity1 child1) { + this.child1 = child1; + } + + public ChildEntity1 getChild2() { + return child2; + } + + public void setChild2(ChildEntity1 child2) { + this.child2 = child2; + } + + public ChildEntity1 getChild3() { + return child3; + } + + public void setChild3(ChildEntity1 child3) { + this.child3 = child3; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof RootEntity)) return false; + + RootEntity that = (RootEntity) o; + + if (data1 != null ? !data1.equals(that.data1) : that.data1 != null) return false; + if (data2 != null ? !data2.equals(that.data2) : that.data2 != null) return false; + if (date1 != null ? !date1.equals(that.date1) : that.date1 != null) return false; + if (id != null ? !id.equals(that.id) : that.id != null) return false; + if (number1 != null ? !number1.equals(that.number1) : that.number1 != null) return false; + if (number2 != null ? !number2.equals(that.number2) : that.number2 != null) return false; + + return true; + } + + public int hashCode() { + int result; + result = (id != null ? id.hashCode() : 0); + result = 31 * result + (data1 != null ? data1.hashCode() : 0); + result = 31 * result + (data2 != null ? data2.hashCode() : 0); + result = 31 * result + (number1 != null ? number1.hashCode() : 0); + result = 31 * result + (number2 != null ? number2.hashCode() : 0); + result = 31 * result + (date1 != null ? date1.hashCode() : 0); + return result; + } +} diff --git a/envers/src/test/resources/hibernate.test.cfg.xml b/envers/src/test/resources/hibernate.test.cfg.xml index c48f2074f6..db36d18262 100644 --- a/envers/src/test/resources/hibernate.test.cfg.xml +++ b/envers/src/test/resources/hibernate.test.cfg.xml @@ -17,13 +17,15 @@ sa - + - + 100--> + + \ No newline at end of file