Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EclipseLink/Examples/JPA/Simulation"

m (Processor Architecture)
m (Design)
Line 45: Line 45:
 
==Design==
 
==Design==
 
===JPA Data Model===
 
===JPA Data Model===
===Hardware===
 
====Prototype 3 Dimensional Hypercube====
 
*The following diagram illustrates via block diagram the layout of a prototype 3 dimensional hypercube architecture at the bottom hardware end of the implementation stack where '''[http://www.eclipselink.org EclipseLink]''' acts as the '''ORM''' persistence layer for both the design and runtime parts of the system.
 
 
[[Image:Prop_3hypercube.jpg]]
 
====Prototype 2 Dimensional SIMD Array====
 
*The following diagrams discuss design issues surrounding a 2 dimensional array of processing module cores - their layout, connection topology and synchronization protocols.
 
=====Design Issue 1: Minimizing Inter-module Connections=====
 
*The following 2 x 8 layout of 2 chips of 8 cores forming a 16 core module is ''not optimum''.
 
[[Image:PropCAS_16core_module_suboptimum_2x8_config_v20100907.jpg]]
 
*The following 4 x 4 layout of 2 chips of 8 cores forming a 16 core module is ''optimum''.
 
[[Image:PropCAS_16core_module_optimum_4x4_config_v20100907.jpg]]
 
*We can reduce the 8 connection paths to 4 by ''reusing'' the corner values of the '''NEWS''' primary connectors - which is only required for the incoming connections - not the outgoing ones.
 
[[Image:PropCAS_16core_module_ext_connect_block_v20100907.jpg]]
 
  
 
==Implementation==
 
==Implementation==

Revision as of 14:51, 9 September 2010

Simulation JPA Application Example

DISCLAIMER: This page reflects investigation into how EclipseLink technology can used as part of - or benefit from integration with other projects. It does NOT imply any formal certification from EclipseLink on these technologies or make any assumptions on the direction of the API. This page is purely experimental speculation.

Purpose

  • This sumulation will serve as a near real world enterprise application that showcases utilizing JPA as the persistence or integration layer of a major hardware/software system application - specifically using EclipseLink JPA as the JPA provider.
  • The software will also showcase the distributed performance capabilities of EclipseLink by using the 1st level cache and an optional 2nd level distributed memory cache in clustered mode using either TopLink Grid or Terracotta EhCache.
  • Additionally, the process and result of this analysis will use and showcase an example UML based design approach.
  • This enterprise application will offer the services of a simulated SIMD Parallel Processor somewhat like the Connection Machine (Ref: Thinking Machines CM-2, MIT Cosmic Cube (MIMD), Burroughs Illiac IV etc.).
    • Why are we choosing an older architecture to simulate?
      • a) The architecture is very clean and closed and even though it is very large - is simple enough to implement.
      • b) The Design by Danny Hillis in his dissertation is out of print as of 2005 and Thinking Machines no longer exists in whole but was partially acquired by Oracle - so we are free to simulate the device in software and hardware.
      • b) The design is proven and static - as it has been superceeded by and incorporated in more powerfull designs).
      • c) The massively parallel processing design of the CM-2 matches our goal of utilizing parallelism at both the thread and multi-core processor level on our plain host machine - an 8 core Intel i7-920 - although at a more granular level.

Goals

  • We would like to explore the following limits of the JPA provider and hosting application server.
    • Performance and Volumetrics: We require 65536 processor objects - but will likely simulate a Kilo (1024) core machine.

Infrastructure

  • OS: Windows 7 64 bit
  • Database: Derby 10.5.3.0
  • JPA provider: EclipseLink 2.2
  • JDK: Sun 1.6.0_17

Analysis

Data Model

Processor Architecture

  • Each CM-2 processor is composed of up to 64k (65536) 1-bit processors arranged in a 12-dimensional hypercube of 16 processors per node.
    • There are 16 1-bit processors per chip along with 1 routing processor per chip.
      • There are 32 cpu chips and 32 ram chips per backplane board
        • There are 16 boards per quadrant
          • There are 8 quadrands to a CM-2
    • We therefore have (2^4=16) x (2^5=32) x (2^4=16) x (2^3=8) = 2^16 = 65536 possible processors in a fully configured system.

Static Class Hierarchy

  • Hypercube (quadrants(1:M), input, output, program)
  • Quadrant (boards(1:M), hypercube(1:1))
  • Board (processorChips(1:M), ramChips(1:M))
  • Chip(A)
    • ProcessorChip (processors (1:M), router (1:1))
    • MemoryChip
  • Processor(A)
    • VectorProcessor(alu, stateMachine, uProgram)
    • RouterProcessor (routers(1:M))

Design

JPA Data Model

Implementation

Business Logic Client

Schema Model

Board.java

@Entity
@Table(name="CM_BOARD")
public class Board implements Serializable {
    @Id
    @GeneratedValue(strategy=TABLE, generator="BOARD_CM_TABLE_GENERATOR")
    @TableGenerator(
        name="BOARD_CM_TABLE_GENERATOR", 
        table="CM_BOARD_SEQ", 
        pkColumnName="SEQ_CM_NAME", 
        valueColumnName="SEQ_CM_COUNT",
        pkColumnValue="CUST_CM_SEQ"
    )
 
    @Column(name="BOARD_ID")    
    private Integer id;
 
    @Version
    @Column(name="BOARD_VERSION")
    private int version;
 
    // If a JoinTable with a JoinColumn is used - then we need a mappedBy on the inverse side here
    @OneToMany(cascade=ALL, mappedBy="board")
    private List<ProcessorChip> processorChips = new ArrayList<ProcessorChip>();
 
    // The M:1 side is the owning side
    @ManyToOne(fetch=EAGER)//LAZY)
    @JoinTable(name="CM_QUADRANT_CM_BOARD", 
            joinColumns = @JoinColumn(name="BOARD_ID"), 
            inverseJoinColumns =@JoinColumn(name="QUADRANT_ID"))   
    private Quadrant quadrant;
 
    public List<VectorProcessor> getVectorProcessors() {
        List<VectorProcessor> allProcessors = new ArrayList<VectorProcessor>();
        for(ProcessorChip aProcessorChip : processorChips) {
            allProcessors.addAll(aProcessorChip.getVectorProcessors());
        }
        return allProcessors;
    }

Chip.java

@MappedSuperclass
public abstract class Chip implements Serializable {
    @Id
    @GeneratedValue(strategy=TABLE, generator="CHIP_CM_TABLE_GENERATOR")
    @TableGenerator(
        name="CHIP_CM_TABLE_GENERATOR", 
        table="CM_CHIP_SEQ", 
        pkColumnName="SEQ_CM_NAME", 
        valueColumnName="SEQ_CM_COUNT",
        pkColumnValue="CUST_CM_SEQ"
    )
 
    @Column(name="CHIP_ID")    
    private Integer id;
 
    // The M:1 side is the owning side
    @ManyToOne(fetch=EAGER)//LAZY)
    @JoinTable(name="CM_BOARD_CM_CHIP", 
            joinColumns = @JoinColumn(name="CHIP_ID"), 
            inverseJoinColumns =@JoinColumn(name="BOARD_ID"))   
    private Board board;

Hypercube.java

@Entity
@Table(name="CM_HYPERCUBE")
public class Hypercube implements Serializable {
    @Id
    @GeneratedValue(strategy=TABLE, generator="HYPERCUBE_CM_TABLE_GENERATOR")
    @TableGenerator(
        name="HYPERCUBE_CM_TABLE_GENERATOR", 
        table="CM_HYPERCUBE_SEQ", 
        pkColumnName="SEQ_CM_NAME", 
        valueColumnName="SEQ_CM_COUNT",
        pkColumnValue="CUST_CM_SEQ"
    )
 
    @Column(name="HYPERCUBE_ID")    
    private Integer id;
 
    // If a JoinTable with a JoinColumn is used - then we need a mappedBy on the inverse side here
    @OneToMany(cascade=ALL, mappedBy="hypercube")
    private List<Quadrant> quadrants = new ArrayList<Quadrant>();
 
    public List<VectorProcessor> getVectorProcessors() {
        List<VectorProcessor> allProcessors = new ArrayList<VectorProcessor>();
        for(Quadrant aQuadrant : quadrants) {
            allProcessors.addAll(aQuadrant.getVectorProcessors());
        }
        return allProcessors;
    }

Processor.java

@MappedSuperclass
public abstract class Processor implements Serializable {
    @Id
    @GeneratedValue(strategy=TABLE, generator="PROCESSOR_CM_TABLE_GENERATOR")
    @TableGenerator(
        name="PROCESSOR_CM_TABLE_GENERATOR", 
        table="CM_PROCESSOR_SEQ", 
        pkColumnName="SEQ_CM_NAME", 
        valueColumnName="SEQ_CM_COUNT",
        pkColumnValue="CUST_CM_SEQ"
    )
 
    @Column(name="PROCESSOR_ID")    
    private Integer id;

ProcessorChip.java

@Entity
@Table(name="CM_PROCESSORCHIP")
public class ProcessorChip extends Chip implements Serializable {
    private List<Boolean> stateMachine;
    private boolean input;
    private boolean output;
    private ProcessorChip leftChip;
    private ProcessorChip rightChip;
    private ProcessorChip upChip;
 
    @OneToOne
    @JoinColumn(name="PROCESSOR_ID")
    private ProcessorChip downChip;
 
    // If a JoinTable with a JoinColumn is used - then we need a mappedBy on the inverse side here
    @OneToMany(cascade=ALL, mappedBy="besideProcessorChip")
    private List<ProcessorChip> adjacentChips = new ArrayList<ProcessorChip>();
    // The M:1 side is the owning side
    @ManyToOne(fetch=EAGER)//LAZY)
    @JoinTable(name="CM_PROCESSOR_CM_PROCESSOR", 
            joinColumns = @JoinColumn(name="PROCESSOR_ID"), 
            inverseJoinColumns =@JoinColumn(name="PROCESSOR_ID"))   
    private ProcessorChip besideProcessorChip;
 
    // If a JoinTable with a JoinColumn is used - then we need a mappedBy on the inverse side here
    @OneToMany(cascade=ALL, mappedBy="processorChip")
    private List<VectorProcessor> vectorProcessors = new ArrayList<VectorProcessor>();

Quadrant.java

@Entity
@Table(name="CM_QUADRANT")
public class Quadrant implements Serializable {
    @Id
    @GeneratedValue(strategy=TABLE, generator="QUADRANT_CM_TABLE_GENERATOR")
    @TableGenerator(
        name="QUADRANT_CM_TABLE_GENERATOR", 
        table="CM_QUADRANT_SEQ", 
        pkColumnName="SEQ_CM_NAME", 
        valueColumnName="SEQ_CM_COUNT",
        pkColumnValue="CUST_CM_SEQ"
    )
 
    @Column(name="QUADRANT_ID")    
    private Integer id;
 
    // If a JoinTable with a JoinColumn is used - then we need a mappedBy on the inverse side here
    @OneToMany(cascade=ALL, mappedBy="quadrant")
    private List<Board> boards = new ArrayList<Board>();
 
    // The M:1 side is the owning side
    @ManyToOne(fetch=EAGER)//LAZY)
    @JoinTable(name="CM_HYPERCUBE_CM_QUADRANT", 
            joinColumns = @JoinColumn(name="QUADRANT_ID"), 
            inverseJoinColumns =@JoinColumn(name="HYPERCUBE_ID"))   
    private Hypercube hypercube;
 
 
    public List<VectorProcessor> getVectorProcessors() {
        List<VectorProcessor> allProcessors = new ArrayList<VectorProcessor>();
        for(Board aBoard : boards) {
            allProcessors.addAll(aBoard.getVectorProcessors());
        }
        return allProcessors;
    }

VectorProcessor.java

@Entity
@Table(name="CM_VECTORPROCESSOR")
public class VectorProcessor extends Processor implements Serializable {
    // The M:1 side is the owning side
    @ManyToOne(fetch=EAGER)//LAZY)
    @JoinTable(name="CM_CHIP_CM_PROCESSOR", 
            joinColumns = @JoinColumn(name="PROCESSOR_ID"), 
            inverseJoinColumns =@JoinColumn(name="CHIP_ID"))   
    private ProcessorChip processorChip;

CM2Console.java

  • This is a minimum Java SE JPA client
package org.eclipse.persistence.example.jpa.cm.presentation;
 
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.metamodel.Metamodel;
 
import org.eclipse.persistence.example.jpa.cm.business.Board;
import org.eclipse.persistence.example.jpa.cm.business.Hypercube;
import org.eclipse.persistence.example.jpa.cm.business.ProcessorChip;
import org.eclipse.persistence.example.jpa.cm.business.Quadrant;
import org.eclipse.persistence.example.jpa.cm.business.VectorProcessor;
import org.eclipse.persistence.example.jpa.cm.integration.CM2;
 
public class CM2Console {
 
    CM2 connectionMachine;
 
    public CM2Console() {
        connectionMachine = new CM2();
    }
 
   public CM2 getConnectionMachine() {
        return connectionMachine;
    }
 
    public void setConnectionMachine(CM2 connectionMachine) {
        this.connectionMachine = connectionMachine;
    }
 
    // Application managed EMF and EM
    public EntityManagerFactory emf  = null;
    public EntityManager entityManager = null;
    // Reference the database specific persistence unit in persistence.xml
    public static final String PU_NAME_CREATE = "CMJPA_create";    
 
    /**
     * Create the EMF and EM and start a transaction (out of container context)
     * @param puName
     */
    private void initialize(String puName) {
        try {
            // Initialize an application managed JPA emf and em via META-INF
            emf  = Persistence.createEntityManagerFactory(puName);
            entityManager = emf.createEntityManager();            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    /**
     * Close the application managed EM and EMF
     */
    @Override
    public void finalize() {
        // close JPA
        try {
            if(null != getEntityManager()) {
                getEntityManager().close();
                getEmf().close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    private void populate(PrintWriter out) {
        // register atomic entities first before creating relationships
        try {
            EntityManager em = getEntityManager();
            if(null == em) {
                System.out.println("EntityManager is null: Check your persistence.xml properties");
            } else {
                EntityTransaction transaction = em.getTransaction();
                if(null == transaction) {
                    System.out.println("Cannot get a transaction from entityManager: " + em);
                } else {                    
                    transaction.begin();
 
                    // Insert schema and classes into the database
                    CM2 cm2 = new CM2();
                    // 1 Hypercube
                    Hypercube hypercube = new Hypercube();        
                    // 8 Quadrants
                    List<Quadrant> quadrants = new ArrayList<Quadrant>();
                    for(int i=0; i<8; i++) {
                        Quadrant aQuadrant = new Quadrant();
                        aQuadrant.setHypercube(hypercube);
                        quadrants.add(aQuadrant);
                        // 16 Backplane Boards
                        List<Board> boards = new ArrayList<Board>();
                        for(int j=0; j<16; j++) {
                            Board aBoard = new Board();
                            aBoard.setQuadrant(aQuadrant);
                            boards.add(aBoard);
                            // 32 processor chips per board
                            List<ProcessorChip> chips = new ArrayList<ProcessorChip>();
                            for(int k=0; k<32; k++) {
                                ProcessorChip aChip = new ProcessorChip();
                                aChip.setBoard(aBoard);
                                chips.add(aChip);
                                // 16 vector processors per chip
                                List<VectorProcessor> processors = new ArrayList<VectorProcessor>();
                                for(int l=0; l<16; l++) {
                                    VectorProcessor aProcessor = new VectorProcessor();
                                    aProcessor.setProcessorChip(aChip);
                                    processors.add(aProcessor);
                                    em.merge(aProcessor);
                                }
                                aChip.setProcessors(processors);
                                em.merge(aChip);
                            }
                            aBoard.setChips(chips);
                            em.merge(aBoard);
                        }
                        aQuadrant.setBoards(boards);
                        em.merge(aQuadrant);
                    }
                    hypercube.setQuadrants(quadrants);        
                    cm2.setHypercube(hypercube);                    
                    em.merge(hypercube);
 
                    // 8 Quadrants
                    long processorCount = 0;
                    em.persist(hypercube);
                    for(Quadrant aQuadrant : hypercube.getQuadrants()) {
                        em.persist(aQuadrant);
                        // 16 Backplane Boards
                        for(Board aBoard : aQuadrant.getBoards()) {
                            em.persist(aBoard);
                            // 32 processor chips per board
                            for(ProcessorChip aChip : aBoard.getProcessorChips()) {
                                em.persist(aChip);
                                // 16 vector processors per chip
                                for(VectorProcessor aProcessor : aChip.getVectorProcessors()) {
                                    //System.out.println("_persisting: " + count++ + " : " + aProcessor);                                    
                                    em.persist(aProcessor);
                                    processorCount++;
                                }                                
                            }                            
                        }                        
                    }
                    System.out.println("_persisted " + processorCount + " Processor Entities");
                    System.out.println("_All Processors: " + hypercube.getVectorProcessors().size());
                    Metamodel aMetamodel = em.getMetamodel();
                    System.out.println("_Metamodel: " + aMetamodel);
                }
 
                // Store objects        
                transaction.commit();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }        
    }
 
    public EntityManagerFactory getEmf() {
        return emf;
    }
 
    public void setEmf(EntityManagerFactory emf) {
        this.emf = emf;
    }
 
    public EntityManager getEntityManager() {
        return entityManager;
    }
 
    public void setEntifyManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
 
    public static void main(String[] args) {
        CM2Console aConsole = new CM2Console();
        aConsole.initialize(PU_NAME_CREATE);
        aConsole.populate(null);
        aConsole.finalize();
        System.out.println(aConsole.getConnectionMachine());
        System.exit(0);
 
    }
}

Persistence Unit

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
	<persistence-unit name="CMJPA_create" transaction-type="RESOURCE_LOCAL">
	<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
		<class>org.eclipse.persistence.example.jpa.cm.business.Board</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.Hypercube</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.MemoryChip</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.ProcessorChip</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.Quadrant</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.RouterProcessor</class>
		<class>org.eclipse.persistence.example.jpa.cm.business.VectorProcessor</class>
       <properties>
            <property name="eclipselink.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
            <property name="eclipselink.target-database" value="org.eclipse.persistence.platform.database.oracle.OraclePlatform"/>            
            <property name="eclipselink.jdbc.url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
            <property name="eclipselink.jdbc.user" value="scott"/>
            <property name="eclipselink.jdbc.password" value="pw"/>
            <!-- property name="eclipselink.logging.level" value="ALL"/-->            
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
            <property name="eclipselink.ddl-generation.output-mode" value="database"/>
       </properties>
	</persistence-unit>
</persistence>

Testing

  • In order to accommidate a 65MB heap size use the JVM parameter
    • -Xmx1024m

Console Output

Logs

_persisted 65536 Processor Entities
_All Processors: 65536
_Metamodel: MetamodelImpl@31301308 [ 11 Types: , 9 ManagedTypes: , 7 EntityTypes: , 2 MappedSuperclassTypes: , 0 EmbeddableTypes: ]
[EL Info]: 2009-09-01 15:52:30.633--ServerSession(23979164)--file:/E:/wse/view_w35a/CM2JPA/bin/-CMJPA_create logout successful
org.eclipse.persistence.example.jpa.cm.integration.CM2@2a72b6

Appendices

References

Back to the top