Hey Michael, I took a very quick look, I think understand it, looks like it attempts to get nodes by id starting from 0 until highest possible ID. public synchronized boolean hasNext() { while ( currentNode == null && currentNodeId <= highId ) { try { currentNode = getNodeById( currentNodeId++ ); } catch ( NotFoundException e ) { // ok we try next } } return currentNode != null; } (seems to work even for when neo4j recycles deleted ids; highId=100012 in my case where I had 100,011 relationships each with unique nodes, so likely 100,012 nodes)
Thank you for pointing me to that, I will consider doing the same with getRelationshipById() and bench them both xD Done, looks like it halves the time when using getAllRels() ie. (output) counting inside the same transaction... Node `one` has 1,753,000 out rels, time=10,235,246,378 tx.finish() time=1,070,892,633 counting one's outgoing rels (outside of initial transaction)... Node `one` has 1,753,000 out rels, time=1,743,920,993 counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=26,404,843,957 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=699,410,620 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,667,748,552 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=655,286,990 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=*1,261*,898,459 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=*663*,559,121 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,257,557,629 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=637,826,233 ns Shutting down database ... and the sample program for this(I did have to add getAllRels() which is similar with getAllNodes()): -------------------- in EmbeddedGraphDbImpl.java public Iterable<Relationship> getAllRels() { return new Iterable<Relationship>() { @Override public Iterator<Relationship> iterator() { long highId = nodeManager.getHighestPossibleIdInUse( Relationship.class ); return new AllRelsIterator( highId ); } }; } private class AllRelsIterator implements Iterator<Relationship> { private final long highId; private long currentRelId = 0; private Relationship currentRel = null; AllRelsIterator( long highId ) { this.highId = highId; } @Override public synchronized boolean hasNext() { while ( currentRel == null && currentRelId <= highId ) { try { currentRel = getRelationshipById( currentRelId++ ); } catch ( NotFoundException e ) { // ok we try next } } return currentRel != null; } @Override public synchronized Relationship next() { if ( !hasNext() ) { throw new NoSuchElementException(); } Relationship nextNode = currentRel; currentRel = null; return nextNode; } @Override public void remove() { throw new UnsupportedOperationException(); } } -------------- /** * Licensed to Neo Technology under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Neo Technology licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.neo4j.examples; import java.io.*; import java.text.*; import org.neo4j.graphdb.*; import org.neo4j.graphdb.index.*; import org.neo4j.kernel.*; public class CalculateShortestPath { private static final int SHOWINFO_IF_COUNTING_REL_TOOK_MORE_THAN_ns = 2 * 300; private static final int SHOWINFO_IF_REL_TOOK_MORE_THAN_ns = 30000; private static final int SHOWEVERY_xTH_REL = 10000; private static final int HOWMANY_RELATIONSHIPS = 109000; private static final String DB_PATH = "neo4j-shortest-path"; private static final String NAME_KEY = "name"; private static RelationshipType KNOWS = DynamicRelationshipType .withName( "KNOWS" ); private static GraphDatabaseService graphDb; private static Index<Node> indexService; private static DecimalFormat commaDelimitedFormatter = new DecimalFormat( "###,###" ); public static String number( double val ) { return commaDelimitedFormatter.format( val ); } public static void main( final String[] args ) { // deleteFileOrDirectory( new File( DB_PATH ) );// XXX: graphDb = new EmbeddedGraphDatabase( DB_PATH ); registerShutdownHook(); indexService = graphDb.index().forNodes( "nodes" ); Transaction rootTx; rootTx = graphDb.beginTx(); Node one = getOrCreateNode( "one" ); DynamicRelationshipType moo = DynamicRelationshipType.withName( "moo" ); try { for ( int i = 1; i <= HOWMANY_RELATIONSHIPS; i++ ) { long start = System.nanoTime(); Relationship rel = one.createRelationshipTo( graphDb.createNode(), moo ); long end = System.nanoTime(); if ( ( i % SHOWEVERY_xTH_REL == 0 ) || ( end - start > SHOWINFO_IF_REL_TOOK_MORE_THAN_ns ) ) { System.out.println( number( i ) + " timeDelta=" + number( end - start ) ); } } System.out.println( "counting inside the same transaction..." ); long start = System.nanoTime(); Iterable<Relationship> rel = one.getRelationships( Direction.OUTGOING, moo ); long count = 0; long tstart = 0; for ( Relationship relationship : rel ) { // long tend = System.nanoTime(); count++; // if ( ( tend - tstart > SHOWINFO_IF_COUNTING_REL_TOOK_MORE_THAN_ns ) ) { // System.out.println( number( count ) + " timeDelta=" + number( tend - tstart ) ); // } // tstart = System.nanoTime(); } long end = System.nanoTime(); System.out.println( "Node `" + one.getProperty( NAME_KEY ) + "` has " + number( count ) + " out rels, time=" + number( end - start ) ); rootTx.success(); } finally { long start = System.nanoTime(); rootTx.finish(); long end = System.nanoTime(); System.out.println( "tx.finish() time=" + number( end - start ) ); } System.out.println( "counting one's outgoing rels (outside of initial transaction)..." ); long start = System.nanoTime(); Iterable<Relationship> rel = one.getRelationships( Direction.OUTGOING, moo ); long count = 0; for ( Relationship relationship : rel ) { count++; } long end = System.nanoTime(); System.out.println( "Node `" + one.getProperty( NAME_KEY ) + "` has " + number( count ) + " out rels, time=" + number( end - start ) ); int repeat = 3; do { System.out.println( "counting all outgoing rels of all nodes ... via getAllNodes" ); count = 0; start = System.nanoTime(); Iterable<Node> allNodes = graphDb.getAllNodes(); for ( Node node : allNodes ) { Iterable<Relationship> allRels = node.getRelationships( Direction.OUTGOING ); for ( Relationship relationship : allRels ) { count++; } } end = System.nanoTime(); System.out.println( "all relationships in the database = " + number( count ) + " timedelta=" + number( end - start ) + " ns" ); System.out.println( "counting all Relationships ... via getAllRels" ); count = 0; start = System.nanoTime(); Iterable<Relationship> allRels = graphDb.getAllRels(); for ( Relationship relationship : allRels ) { count++; } end = System.nanoTime(); System.out.println( "all relationships in the database = " + number( count ) + " timedelta=" + number( end - start ) + " ns" ); } while ( repeat-- > 0 ); } private static Node getOrCreateNode( String name ) { Node node = indexService.get( NAME_KEY, name ).getSingle(); if ( node == null ) { System.out.println( "creating new node with name=" + name ); node = graphDb.createNode(); node.setProperty( NAME_KEY, name ); indexService.add( node, NAME_KEY, name ); } return node; } private static void registerShutdownHook() { // Registers a shutdown hook for the Neo4j instance so that it // shuts down nicely when the VM exits (even if you "Ctrl-C" the // running example before it's completed) Runtime.getRuntime().addShutdownHook( new Thread() { @SuppressWarnings( "synthetic-access" ) @Override public void run() { System.out.println( "Shutting down database ..." ); graphDb.shutdown(); } } ); } private static void deleteFileOrDirectory( File file ) { if ( file.exists() ) { if ( file.isDirectory() ) { for ( File child : file.listFiles() ) { deleteFileOrDirectory( child ); } } file.delete(); } } } ======== here's another output when no additions were done (using same sample program) but trying to count the relationships via getAllRels first, then getAllNodes, and repeating this block: counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=*10,1*02,256,698 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=*29,9*02,912,485 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=687,562,153 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,377,601,567 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=*648*,269,229 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=*1,371*,030,811 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=756,425,427 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,256,402,192 ns Shutting down database ... ====== and here's another way: counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=*10,154*,915,686 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=*690*,298,744 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=649,536,192 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=1,978,228,693 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=653,655,768 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=647,365,027 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=*28,549*,060,316 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,355,109,837 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,442,695,434 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,438,563,566 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,366,895,645 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=*1,384*,237,380 ns Shutting down database ... I'll paste the program as it is for this last test (though it's the same one, but a bit reordered): I also cleaned it up some: /** * Licensed to Neo Technology under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Neo Technology licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.neo4j.examples; import java.io.*; import java.text.*; import org.neo4j.graphdb.*; import org.neo4j.graphdb.index.*; import org.neo4j.kernel.*; public class Copy_2_of_CalculateShortestPath { private static final String DB_PATH = "neo4j-shortest-path"; private static final String NAME_KEY = "name"; private static GraphDatabaseService graphDb; private static Index<Node> indexService; private static DecimalFormat commaDelimitedFormatter = new DecimalFormat( "###,###" ); public static String number( double val ) { return commaDelimitedFormatter.format( val ); } public static void main( final String[] args ) { // deleteFileOrDirectory( new File( DB_PATH ) );// XXX: graphDb = new EmbeddedGraphDatabase( DB_PATH ); registerShutdownHook(); indexService = graphDb.index().forNodes( "nodes" ); Transaction rootTx; Node one = getOrCreateNode( "one" ); DynamicRelationshipType moo = DynamicRelationshipType.withName( "moo" ); int repeat = 5; do { System.out.println( "counting all Relationships ... via getAllRels" ); long count = 0; long start = System.nanoTime(); Iterable<Relationship> allRels = graphDb.getAllRels(); for ( Relationship relationship : allRels ) { count++; } long end = System.nanoTime(); System.out.println( "all relationships in the database = " + number( count ) + " timedelta=" + number( end - start ) + " ns" ); } while ( repeat-- > 0 ); repeat = 5; do { System.out.println( "counting all outgoing rels of all nodes ... via getAllNodes" ); long count = 0; long start = System.nanoTime(); Iterable<Node> allNodes = graphDb.getAllNodes(); for ( Node node : allNodes ) { Iterable<Relationship> allRels2 = node.getRelationships( Direction.OUTGOING ); for ( Relationship relationship : allRels2 ) { count++; } } long end = System.nanoTime(); System.out.println( "all relationships in the database = " + number( count ) + " timedelta=" + number( end - start ) + " ns" ); } while ( repeat-- > 0 ); } private static Node getOrCreateNode( String name ) { Node node = indexService.get( NAME_KEY, name ).getSingle(); if ( node == null ) { System.out.println( "creating new node with name=" + name ); node = graphDb.createNode(); node.setProperty( NAME_KEY, name ); indexService.add( node, NAME_KEY, name ); } return node; } private static void registerShutdownHook() { // Registers a shutdown hook for the Neo4j instance so that it // shuts down nicely when the VM exits (even if you "Ctrl-C" the // running example before it's completed) Runtime.getRuntime().addShutdownHook( new Thread() { @SuppressWarnings( "synthetic-access" ) @Override public void run() { System.out.println( "Shutting down database ..." ); graphDb.shutdown(); } } ); } private static void deleteFileOrDirectory( File file ) { if ( file.exists() ) { if ( file.isDirectory() ) { for ( File child : file.listFiles() ) { deleteFileOrDirectory( child ); } } file.delete(); } } } All in all, a little better, but not making much difference for me at the moment, until reaching some very high amount of relationships or doing lots of counts. Well great, see you later :) counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=11,904,833,914 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=715,916,208 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=652,136,373 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=770,903,756 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=651,695,964 ns counting all Relationships ... via getAllRels all relationships in the database = 1,753,000 timedelta=658,016,686 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=28,067,437,117 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,347,472,686 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,282,134,781 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,309,284,532 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,358,393,266 ns counting all outgoing rels of all nodes ... via getAllNodes all relationships in the database = 1,753,000 timedelta=1,219,737,032 ns Shutting down database ... On Sat, Jul 23, 2011 at 10:51 AM, Michael Hunger < michael.hun...@neotechnology.com> wrote: > An internal implementation would be probably faster. > > If timing is that critical for you, you can have a look in > EmbeddedGraphDbImpl.getAllNodes() and implement a similar solution for > relationships. > > Cheers > > Michael > > Am 23.07.2011 um 04:20 schrieb John cyuczieekc: > > > Hey Jim, > > I am sort of glad to hear that, maybe in the future I could see a method > > like getAllRelationships(), or not, np :) > > Yes, using Michael's code works, but ... > > total relations count=100,011 timedelta=3,075,897,991 ns > > it kind of takes 3 seconds (when not cached) to count 100k relationships > > (considering there are 100k+2 unique nodes too) > > when cached: > > total relations count=100,011 timedelta=154,673,763 ns > > > > Still, it's pretty fast, but I have to wonder if it would be faster if > using > > relationships directly :) > > > > Either way, wish y'all a great day! > > > > > > On Sat, Jul 23, 2011 at 3:57 AM, Jim Webber <j...@neotechnology.com> > wrote: > > > >> Hi John, > >> > >> Relationships are stored in a different store than nodes. This enables > >> Neo4j to manage lifecycle events (like caching) for nodes and > relationships > >> separately. > >> > >> Neo4j really is a graph DB, not a triple store masquerading as a graph > DB. > >> > >> Nonetheless, that code Michael sent still works :-) > >> > >> Jim > >> _______________________________________________ > >> Neo4j mailing list > >> User@lists.neo4j.org > >> https://lists.neo4j.org/mailman/listinfo/user > >> > > _______________________________________________ > > Neo4j mailing list > > User@lists.neo4j.org > > https://lists.neo4j.org/mailman/listinfo/user > > _______________________________________________ > Neo4j mailing list > User@lists.neo4j.org > https://lists.neo4j.org/mailman/listinfo/user > _______________________________________________ Neo4j mailing list User@lists.neo4j.org https://lists.neo4j.org/mailman/listinfo/user