Yeah, that makes sense.

Alexey
2001 Honda CBR600F4i (CCS)
1992 Kawasaki EX500
http://azinger.blogspot.com
http://bsheet.sourceforge.net
http://wcollage.sourceforge.net



--- On Fri, 11/14/08, Ben Schulz <[EMAIL PROTECTED]> wrote:

> From: Ben Schulz <[EMAIL PROTECTED]>
> Subject: [The Java Posse] Re: single-threaded vs concurrent performance on 
> dual-core
> To: "The Java Posse" <[email protected]>
> Date: Friday, November 14, 2008, 7:00 PM
> Playing one round is probably in the (low) 10E2 ticks, so in
> relative
> terms synchronization overhead of the thread pool is
> probably pretty
> high compared to the non existent synchronization overhead
> of the
> single threaded executor
> 
> With kind regards
> Ben
> 
> On 14 Nov., 23:36, Alexey Zinger
> <[EMAIL PROTECTED]> wrote:
> > Sure, I realize how difficult it is to assess these
> things, especially sight unseen.  I was mostly fishing to
> see if there was a known issue with the concurrency API or
> anything like that.
> >
> > But let me answer your questions and I'll post the
> part that invokes concurrency as well.
> >
> > At the moment I don't have access to a Linux box,
> but I'll see if I can get this stuff run on one.
> >
> > Not synchronizing on anything.  When I posted the
> output, I was in fact using Math.random() API, which,
> according to the JDK Javadocs, can synchronize, so I
> switched to using java.util.Random.nextInt(int) off a
> separate Random object, which is what the Javadoc tells you
> to do if you're running in multiple threads.  That
> actually hurt the single-threaded run by a few seconds and
> didn't seem to affect the concurrent mode.
> >
> > I've run it in both server and client mode with
> not perceptible difference.  I've also experimented
> with different heap allocations, which seems mostly to
> affect the concurrent mode by causing it to run out of heap
> if not given enough memory.  Otherwise, there doesn't
> seem to be much of a difference.
> >
> > As to the number of threads in concurrent mode,
> I've experimented with different setups, but for now
> I've settled on running each player as separate Future
> objects, so that makes 3 threads in concurrent mode, and
> each of those spawns up to separate Future objects for each
> game play, limited to 1000 threads in concurrent mode.
> >
> > Here's the interesting part:
> >
> > package zinger.goats;
> >
> > import java.util.*;
> > import java.util.concurrent.*;
> >
> > public class Play
> > {
> >         public static class Tester implements
> Callable<String>
> >         {
> >                 protected final Player player;
> >                 protected final int tries;
> >                 protected final
> ExecutorService executor;
> >
> >                 public Tester(final Player
> player, final int tries, final ExecutorService executor)
> >                 {
> >                         this.player =
> player;
> >                         this.tries =
> tries;
> >                         this.executor =
> executor;
> >                 }
> >
> >                 public String call()
> >                 {
> >                         return
> Play.testPlayer(this.player, this.tries, this.executor);
> >                 }
> >         }
> >
> >         public static void main(final String...
> args)
> >         {
> >                 final long startMS =
> System.currentTimeMillis();
> >                 final int tries =
> Integer.parseInt(args[0]);
> >                 final int maxThreads =
> args.length > 1 ? Integer.parseInt(args[1]) : 1;
> >                 final ExecutorService
> testExecutor = maxThreads > 1 ?  
> >                        
> Executors.newFixedThreadPool(Math.min(3, maxThreads)) :
> >                        
> Executors.newSingleThreadExecutor();
> >                 final ExecutorService
> gameExecutor = maxThreads > 1 ?
> >                        
> Executors.newFixedThreadPool(Math.min(maxThreads, tries)) :
> >                        
> Executors.newSingleThreadExecutor();
> >                 try
> >                 {
> >                         final
> List<Future<String>> futures = new
> ArrayList<Future<String>>(3);
> >                        
> futures.add(testExecutor.submit(new Play.Tester(new
> RandomPlayer(), tries, gameExecutor)));
> >                        
> futures.add(testExecutor.submit(new Play.Tester(new
> NeverChangePlayer(), tries, gameExecutor)));
> >                        
> futures.add(testExecutor.submit(new Play.Tester(new
> AlwaysChangePlayer(), tries, gameExecutor)));
> >                        
> for(Future<String> future : futures)
> >                         {
> >                                 try
> >                                 {
> >                                    
>     System.out.println(future.get());
> >                                 }
> >                                
> catch(final InterruptedException ex)
> >                                 {
> >                                    
>     ex.printStackTrace();
> >                                 }
> >                                
> catch(final ExecutionException ex)
> >                                 {
> >                                    
>     ex.printStackTrace();
> >                                 }
> >                         }
> >                 }
> >                 finally
> >                 {
> >                        
> System.out.println("Execution time: " +
> ((System.currentTimeMillis() - startMS) / 1000L) +
> "sec.");
> >                        
> testExecutor.shutdown();
> >                        
> gameExecutor.shutdown();
> >                 }
> >         }
> >
> >         public static String testPlayer(final
> Player player, final int tries, final ExecutorService
> executor)
> >         {
> >                 final StringBuilder sb = new
> StringBuilder();
> >                 int carCount = 0;
> >                 int goatCount = 0;
> >                 final int[] carDistribution =
> new int[3];
> >                 final int[] goatDistribution =
> new int[3];
> >
> >                 final List<Game> games =
> new ArrayList<Game>(tries);
> >                 final
> List<Future<?>> futures = new
> ArrayList<Future<?>>(tries);
> >                 for(int i = 0; i < tries;
> ++i)
> >                 {
> >                         final Game game =
> new Game(player, new Random());
> >                         games.add(game);
> >                        
> futures.add(executor.submit(game));
> >                 }
> >
> >                 for(int i = 0; i < tries;
> ++i)
> >                 {
> >                         try
> >                         {
> >                                
> futures.get(i).get();
> >                         }
> >                         catch(final
> InterruptedException ex)
> >                         {
> >                                
> ex.printStackTrace();
> >                                
> continue;
> >                         }
> >                         catch(final
> ExecutionException ex)
> >                         {
> >                                
> ex.printStackTrace();
> >                                
> continue;
> >                         }
> >                         final Game game =
> games.get(i);
> >                        
> switch(game.getPrize())
> >                         {
> >                                 case
> CAR:
> >                                
> ++carCount;
> >                                 break;
> >
> >                                 case
> GOAT:
> >                                
> ++goatCount;
> >                                 break;
> >                         }
> >                         for(int doorIndex
> = 0; doorIndex < game.doorView.size(); ++doorIndex)
> >                         {
> >                                 final
> Game.Door door = game.doorView.get(doorIndex);
> >                                
> switch(door.open())
> >                                 {
> >                                    
>     case CAR:
> >                                    
>     ++carDistribution[doorIndex];
> >                                    
>     break;
> >
> >                                    
>     case GOAT:
> >                                    
>     ++goatDistribution[doorIndex];
> >                                    
>     break;
> >                                 }
> >                         }
> >                 }
> >
> >                
> sb.append(player.getDescription()).append(" won
> ").append(carCount).append(" cars and
> ").append(goatCount).append(" goats.\n");
> >                 sb.append("Cars were
> distributed as follows:");
> >                 for(final int prizeCount :
> carDistribution)
> >                        
> sb.append('\t').append(prizeCount);
> >                 sb.append("\nGoats
> were distributed as follows:");
> >                 for(final int prizeCount :
> goatDistribution)
> >                        
> sb.append('\t').append(prizeCount);
> >                 sb.append('\n');
> >                 return sb.toString();
> >         }
> >
> > }
> >
> > And here's how it's invoked:
> >
> > <?xml version="1.0"?>
> > <project name="Goats"
> default="run">
> >         <property name="tries"
> value="1000000"/>
> >         <property name="maxThreads"
> value="1000"/>
> >
> >         <target name="init">
> >                 <mkdir
> dir="${basedir}/cls"/>
> >         </target>
> >
> >         <target name="compile"
> depends="init">
> >                 <javac
> destdir="${basedir}/cls"
> srcdir="${basedir}/src"
> debug="true"/>
> >         </target>
> >
> >         <target name="run"
> depends="compile">
> >                 <echo message="Tries:
> ${tries}; max threads: ${maxThreads}."/>
> >                 <echo
> message="Single-threaded..."/>
> >                 <echo/>
> >                 <java
> classname="zinger.goats.Play"
> classpath="${basedir}/cls" fork="true"
> failonerror="true">
> >                         <!--<jvmarg
> value="-Xmx1000m"/>-->
> >                         <jvmarg
> value="-server"/>
> >                         <arg
> value="${tries}"/>
> >                 </java>
> >                 <echo/>
> >                 <echo
> message="Concurrent..."/>
> >                 <java
> classname="zinger.goats.Play"
> classpath="${basedir}/cls" fork="true"
> failonerror="true">
> >                         <jvmarg
> value="-Xmx1000m"/>
> >                         <jvmarg
> value="-server"/>
> >                         <arg
> value="${tries}"/>
> >                         <arg
> value="${maxThreads}"/>
> >                 </java>
> >         </target>
> > </project>
> >
> > And the latest output:
> >
> > Tries: 1000000; max threads: 1000.
> > Single-threaded...
> >
> > Random Player won 499013 cars and 500987 goats.
> > Cars were distributed as follows:       332940
>  333982  333078
> > Goats were distributed as follows:      667060
>  666018  666922
> >
> > Never Change Player won 333605 cars and 666395 goats.
> > Cars were distributed as follows:       332908
>  333852  333240
> > Goats were distributed as follows:      667092
>  666148  666760
> >
> > Always Change Player won 665827 cars and 334173 goats.
> > Cars were distributed as follows:       333435
>  332470  334095
> > Goats were distributed as follows:      666565
>  667530  665905
> >
> > Execution time: 30sec.
> >
> > Concurrent...
> > Random Player won 500155 cars and 499845 goats.
> > Cars were distributed as follows:       333661
>  334231  332108
> > Goats were distributed as follows:      666339
>  665769  667892
> >
> > Never Change Player won 333164 cars and 666836 goats.
> > Cars were distributed as follows:       332788
>  333709  333503
> > Goats were distributed as follows:      667212
>  666291  666497
> >
> > Always Change Player won 666344 cars and 333656 goats.
> > Cars were distributed as follows:       333603
>  333938  332459
> > Goats were distributed as follows:      666397
>  666062  667541
> >
> > Execution time: 39sec.
> >
> > --- On Fri, 11/14/08, Reinier Zwitserloot
> <[EMAIL PROTECTED]> wrote:
> >
> > > From: Reinier Zwitserloot
> <[EMAIL PROTECTED]>
> > > Subject: [The Java Posse] Re: single-threaded vs
> concurrent performance on dual-core
> > > To: "The Java Posse"
> <[email protected]>
> > > Date: Friday, November 14, 2008, 3:03 PM
> > > There are a gazillion factors at work here, from
> bugs in
> > > your code to
> > > JVM implementation to kernel thread scheduler.
> Without
> > > exquisite
> > > detail, I don't think its even possible to
> shed some
> > > light as to why
> > > you're seeing a slight (less than doubling is
> > > 'slight', in meaningful
> > > profiling). Even with all that info, I doubt -I-
> could tell
> > > you,
> > > though I cannot of course speak for other posse
> listeners.
> >
> > > A few quick and dirty ones:
> >
> > >  - try this on linux 2.6. It has a kick ass
> thread
> > > scheduler.
> > >  - are you synchronizing on anything, or did you
> add
> > > Thread.sleep/wait
> > > anywhere? That tends to make stuff worse.
> > >  - are you on the server VM? I don't think
> this matters
> > > anymore in
> > > 6u10, though, as the mixed mode VM is pretty
> smart, or so I
> > > hear.
> > >  - are you using exactly 2 threads, slightly
> more than
> > > that, or a
> > > massive amount of them?
> >
> > > On Nov 14, 7:04 pm, Alexey Zinger
> > > <[EMAIL PROTECTED]> wrote:
> > > > A little while ago I wrote a simulation of
> the Monty
> > > Hall puzzle.  The simulator is given 3 players
> of different
> > > strategies (one makes a decision at random, the
> other never
> > > switches doors, and the third always switches)
> and runs each
> > > player through a configurable number of games,
> outputting
> > > each player's outcomes at the end.  Seems
> fairly simple
> > > and everything was working as expected.
> >
> > > > Seeing as I have a dual core machine (XP
> Pro, JRE
> > > 1.6_10), I looked at the way the CPU was being
> utilized and
> > > to my surprise I saw a fairly even utilization of
> both
> > > cores, despite the program being
> single-threaded.  Then I
> > > decided to make the simulator multi-threaded and
> see what
> > > would happen to the utilization graph and speed
> of the
> > > application.  I converted the
> > > >  code invoking the game generation and
> running API to
> > > use Java concurrency framework, which also game
> me good
> > > control over how many threads I wanted to use or
> if I wanted
> > > to run everything single-threaded still.  Once I
> got
> > > everything working again, I was dismayed to see
> somewhat
> > > uneven
> >
> > ...
> >
> > Erfahren Sie mehr »
> 

      

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to