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
-~----------~----~----~----~------~----~------~--~---