Performance vs Java

103 views
Skip to first unread message

Michael Lewis

unread,
Jan 9, 2014, 1:21:36 PM1/9/14
to disrup...@googlegroups.com
Hi,
 
I'm not sure if I'm doing a valid like for like comparison. But I have an Events that basically contain two doubles.
I have events for Add, Sub, Mult and Div - each does an addition, subtraction etc... of the two doubles and writes
the result into an instance of a inner 'State' class.
 
The code below show the Java and C# versions that are meant to be identical, but on the same machine,
repeated test show that the Java version is about 50% faster, I think it may be do the ExecuteService parameter.
 
Any ideas on what I may be doing wrong with C# version - see below?

Regards
Mike Lewis
 
Java:
-------
 ExecutorService service = Executors.newFixedThreadPool(7);
        Disruptor<CalculationEvent> disruptor = new Disruptor<>(CalculationEvent.EVENT_FACTORY,65536,service);
 

        final EventHandler<CalculationEvent> adder = new EventHandler<CalculationEvent>() {
            @Override
            public void onEvent(CalculationEvent calculationEvent, long sequenceId, boolean endOfBatch) throws Exception {
                calculationEvent.doCalc(CalculationEvent.Type.add);
            }
        };
        final EventHandler<CalculationEvent> subtractor = new EventHandler<CalculationEvent>() {
            @Override
            public void onEvent(CalculationEvent calculationEvent, long sequenceId, boolean endOfBatch) throws Exception {
                calculationEvent.doCalc(CalculationEvent.Type.sub);
            }
        };
        final EventHandler<CalculationEvent> multiplier = new EventHandler<CalculationEvent>() {
            @Override
            public void onEvent(CalculationEvent calculationEvent, long l, boolean b) throws Exception {
                calculationEvent.doCalc(CalculationEvent.Type.mult);
            }
        };

        final EventHandler<CalculationEvent> divider = new EventHandler<CalculationEvent>() {
            @Override
            public void onEvent(CalculationEvent calculationEvent, long l, boolean b) throws Exception {
                calculationEvent.doCalc(CalculationEvent.Type.div);
            }
        };

        final EventHandler<CalculationEvent> publishResult1 = new EventHandler<CalculationEvent>() {

            @Override
            public void onEvent(CalculationEvent calculationEvent, long l, boolean b) throws Exception {
                /*
                 no-op
                */
            }
        };
        /*
         * This says do add, sub, mult, div in parallel and then do finish.
         */
        disruptor.handleEventsWith(adder,subtractor,multiplier,divider).then(publishResult1);
        RingBuffer<CalculationEvent> ringBuffer = disruptor.start();
        CalculationEventTranslator translator = new CalculationEventTranslator();
        long s = (System.currentTimeMillis());
        //Random r = new Random();
        for (int i=0; i<1500000; ++i) {
            double first = 0.5; //r.nextDouble();
            double second = 0.5; // r.nextDouble();
            ringBuffer.publishEvent(translator,first,second);
        }
        System.out.println("time spent "+ (System.currentTimeMillis() - s) + " ms");
        disruptor.shutdown();
        service.shutdown();
    }
 
C#
--
    var stopWatch = new Stopwatch();
            var distruptor = new Disruptor.Dsl.Disruptor<CalculationEvent>(() => new CalculationEvent(), 65536,
                TaskScheduler.Default);
            var adder = new Adder();
            var subtractor = new Subtractor();
            var multiplier = new Multiplier();
            var divider = new Divider();
            var publisher = new Publisher();
            distruptor.HandleEventsWith(new IEventHandler<CalculationEvent>[]
            {
                adder, subtractor, multiplier, divider
            }).Then( publisher);
            var buffer = distruptor.Start();
            stopWatch.Start();
            //var r = new Random();
            for (var i = 0; i < 1500000; ++i)
            {
                double first = 0.5; //r.NextDouble();
                double second = 0.5; // r.NextDouble();
                var sequence = buffer.Next();
                var entry = buffer[sequence];
                entry.SetCalculationDetails(first,second);
                buffer.Publish(sequence);
            }
            stopWatch.Stop();
            Console.WriteLine("Time spent {0} ms",stopWatch.ElapsedMilliseconds);
            distruptor.Shutdown();

Handlers:
    public class Adder : IEventHandler<CalculationEvent>
    {
        public void OnNext(CalculationEvent data, long sequence, bool endOfBatch)
        {
            data.DoCalc(CalculationEvent.OpCode.Add);
        }
    }
    public class Subtractor : IEventHandler<CalculationEvent>
    {
        public void OnNext(CalculationEvent data, long sequence, bool endOfBatch)
        {
            data.DoCalc(CalculationEvent.OpCode.Sub);
        }
    }
    public class Multiplier : IEventHandler<CalculationEvent>
    {
        public void OnNext(CalculationEvent data, long sequence, bool endOfBatch)
        {
            data.DoCalc(CalculationEvent.OpCode.Mult);
        }
    }
    public class Divider : IEventHandler<CalculationEvent>
    {
        public void OnNext(CalculationEvent data, long sequence, bool endOfBatch)
        {
            data.DoCalc(CalculationEvent.OpCode.Div);
        }
    }
    public class Publisher : IEventHandler<CalculationEvent>
    {
        public void OnNext(CalculationEvent data, long sequence, bool endOfBatch)
        {
        }
    }
Event Class:
using System;
    public class CalculationEvent
    {
        public enum OpCode
        {
            Add, Sub, Div, Mult
        };
        public class State
        {
            public double Add { get; set; }
            public double Sub { get; set; }
            public double Mult { get; set; }
            public double Div { get; set; }
        }
        private double _first;
        private double _second;
        public State CalcState;
        public CalculationEvent()
        {
            CalcState = new State();
        }
        public void SetCalculationDetails(double first, double second)
        {
            _first = first;
            _second = second;
        }
        public void DoCalc(OpCode code)
        {
            try
            {
                switch (code)
                {
                    case OpCode.Add:
                    {
                        CalcState.Add = _first + _second;
                    }
                    break;
                    case OpCode.Div:
                    {
                        CalcState.Div = _first/_second;
                    }
                    break;
                    case OpCode.Mult:
                    {
                        CalcState.Mult = _first*_second;
                    }
                    break;
                    default:
                    {
                        CalcState.Sub = _first - _second;
                    }
                    break;
                }
            }
            catch (Exception e)
            {
             
            }
        }
    }

 

distruptor.Shutdown();

 
 
 

Olivier Deheurles

unread,
Jan 10, 2014, 1:45:36 AM1/10/14
to disrup...@googlegroups.com, disrup...@googlegroups.com
The .NET version is slower than the java version for a few reasons:
 - some low level concurrency primitives available in Java Unsafe class are not exposed in .NET so we use less optimized alternatives in .NET
 - more generally HotSpot does a better job than the CLR JIT and tend to produce more optimized code (more aggressive inlining, etc)
 - also I'm not sure that disruptor.net is up to date with the latest java version (I'm the initial contributor but I've stopped maintaining it, not sure what was ported lately)

Olivier
--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes Disruptor-net.
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse disruptor-ne...@googlegroups.com.
Pour plus d'options, visitez le site https://groups.google.com/groups/opt_out .

Michael Lewis

unread,
Jan 10, 2014, 10:05:44 AM1/10/14
to disrup...@googlegroups.com

Thanks.

Mendel Monteiro-Beckerman

unread,
Jul 20, 2016, 9:31:20 AM7/20/16
to Disruptor-net
Even after porting the latest disruptor changes to the .NET version the java version is still faster.  We're going to try and tune it even more but it Olivier's second point limit's what we can squeeze out of it.

On Friday, January 10, 2014 at 4:05:44 PM UTC+1, Michael Lewis wrote:

Thanks.
Reply all
Reply to author
Forward
0 new messages