Impressive LiveCycle Data Services Numbers

My knowledge of Adobe’s LiveCycle Data Services platform is very limited as I’ve experimented with it only once. However, I’m impressed with the ability of the LiveCycle Data Services (LCDS) to push what seems like a massive amount of messages per second to client machines running Adobe Flash/AIR applications.

http://www.dcooper.org/blog/client/index.cfm?mode=entry&entry=084D6DDA-4E22-1671-5EFB301D42924692

LCDS in their scenario was able to push 400,000 messages to 500 concurrent clients with an average latency of less than 15 milliseconds on a single dual-processor Intel machine.

I know there were some big improvements in the network stack and polling API in Silverlight 4 (in particular the http stack added multiple messages per poll) – but I don’t know how it compares from a performance perspective to the Adobe options.

Anyone know of any real-world comparisons?

Silverlight Stopwatch Class, Part 2

I recently made a fix to a Silverlight stopwatch class I wrote last year.

In doing so, I decided to kick it up a notch.

using (new StopwatchPlus("Constructor"))
{
    //Debug.WriteLine("Initialized: Ellapsed Ticks: {0}, Ellapsed Milliseconds: {1}", sw.EllapsedTicks, sw.EllapsedMilliseconds); InitializeComponent();
    Thread.Sleep(600);            
}

Instead of just a simple Stopwatch class, I added functionality to make it easy to capture timings for blocks of code, output to the Debug Output window, and perform any custom start/stop action.

 

StopwatchPlus sp1 = new StopwatchPlus(sw2 => 
        Debug.WriteLine("Time! {0}", sw2.EllapsedMilliseconds));
Thread.Sleep(500);
sp1.Stop();    // this will call the stopAction defined in the constructor 

 

In non-debug builds, the StopwatchPlus class does not send output to the debug window. (I used the ConditionalAttribute … I know I could have used conditional compilation statements, but I didn’t. :-) ).

using System;
using System.Diagnostics;

namespace WiredPrairie.Silverlight
{
    /// <summary> /// StopwatchPlus is used to measure the general performance of Silverlight functionality. Silverlight /// does not provide a high resolution timer as is available in many operating systems, /// so the resolution of this timer is limited to milliseconds. This class is best used to measure /// the relative performance of functions over many iterations. /// </summary> public sealed class StopwatchPlus : IDisposable {
        private long _startTick;
        private long _elapsed;
        private bool _isRunning;
        private string _name;
        private Action<StopwatchPlus> _startAction;
        private Action<StopwatchPlus> _stopAction;

        /// <summary> /// Creates an instance of the StopwatchPlus class and starts the timer. By /// providing a value to the name parameter, the Debug Console automatically /// will include the current values when the timer was started and stopped with /// this name. /// </summary> /// <param name="name"></param> public StopwatchPlus(string name)
            : this(name, WriteStart, WriteResults) { } 

        /// <summary> /// Creates an instance of the StopwatchPlus class and starts the timer. /// </summary> /// <param name="stopAction">Action to take when the Stop method is called.</param> public StopwatchPlus(Action<StopwatchPlus> stopAction)
            :this(null, stopAction)
        {
        }

        /// <summary> /// Creates an instance of the StopwatchPlus class and starts the timer. /// </summary> /// <param name="startAction">Action to take when the timer starts.</param> /// <param name="stopAction">Action to take when the Stop method is called.</param> public StopwatchPlus(Action<StopwatchPlus> startAction,
            Action<StopwatchPlus> stopAction)
            :this(null, startAction, stopAction)
        {
        }

        /// <summary> /// Creates an instance of the StopwatchPlus class and starts the timer. /// </summary> /// <param name="name">Name of this stop watch (used as output)</param> /// <param name="startAction">Action to take when the timer starts.</param> /// <param name="stopAction">Action to take when the Stop method is called.</param> public StopwatchPlus(string name,
            Action<StopwatchPlus> startAction, 
            Action<StopwatchPlus> stopAction)
        {
            _name = name;
            _startAction = startAction;
            _stopAction = stopAction;
            Start();
        }

        public string Name
        {
            get { return _name; }
        }

        /// <summary> /// Completely resets and deactivates the timer. /// </summary> public void Reset()
        {
            _elapsed = 0;
            _isRunning = false;
            _startTick = 0;
        }

        /// <summary> /// Begins the timer. /// </summary> public void Start()
        {
            if (!_isRunning)
            {
                _startTick = GetCurrentTicks();
                _isRunning = true;
                if (_startAction != null)
                {
                    _startAction(this);
                }
            }
        }

        /// <summary> /// Stops the current timer. /// </summary> public void Stop()
        {
            if (_isRunning)
            {
                _elapsed += GetCurrentTicks() - _startTick;
                _isRunning = false;
                if (_stopAction != null)
                {
                    _stopAction(this);
                }
            }
        }

        /// <summary> /// Gets a value indicating whether the instance is currently recording. /// </summary> public bool IsRunning
        {
            get { return _isRunning; }
        }

        /// <summary> /// Gets the Ellapsed time as a Timespan. /// </summary> public TimeSpan Ellapsed
        {
            get { return TimeSpan.FromMilliseconds(EllapsedMilliseconds); }
        }

        /// <summary> /// Gets the Ellapsed time as the total number of milliseconds. /// </summary> public long EllapsedMilliseconds
        {
            get { return GetCurrentElapsedTicks() / TimeSpan.TicksPerMillisecond; }
        }

        /// <summary> /// Gets the Ellapsed time as the total number of ticks (which is faked /// as Silverlight doesn't have a way to get at the actual "Ticks") /// </summary> public long EllapsedTicks
        {
            get { return GetCurrentElapsedTicks(); }
        }

        private long GetCurrentElapsedTicks()
        {
            return (long)(this._elapsed + (IsRunning ? (GetCurrentTicks() - _startTick) : 0));
        }

        private long GetCurrentTicks()
        {
            // TickCount: Gets the number of milliseconds elapsed since the system started. return Environment.TickCount * TimeSpan.TicksPerMillisecond;
        }

        #region IDisposable Members

        public void Dispose()
        {
            Stop();
        }

        #endregion private static void WriteStart(StopwatchPlus sw)
        {
            WriteStartInternal(sw);
        }

        // This is not called in a Release build [Conditional("DEBUG")]
        private static void WriteStartInternal(StopwatchPlus sw)
        {
            Debug.WriteLine("BEGIN\t{0}", sw._name);

        }

        private static void WriteResults(StopwatchPlus sw)
        {
            WriteResultsInternal(sw);
        }

        // This is not called in a Release build [Conditional("DEBUG")]
        private static void WriteResultsInternal(StopwatchPlus sw) 
        {
            Debug.WriteLine("END\t{0}\t{1}", sw._name, sw.EllapsedMilliseconds);
        }
    }
}

 

My first Windows Phone 7 Experiment

OK, It doesn’t look like much. It’s not. I was experimenting with some CompositionTarget Rendering and WriteableBitmap stuff on the plane ride out to Mix 2010 on Sunday and created a little animating blue line thing. (I don’t know what to to call it). But it was a work in progress.

I took the code and copied it into a Windows Phone 7 Silverlight application and hit run. It worked right out of the box. (Using the CTP download from here).

image

CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);

The event:

void CompositionTarget_Rendering(object sender, EventArgs e)
{
    int indx = _shapes.Count - 1;
    double littleCircleHeight = littleCircle.ActualHeight;

    while (indx >= 0)
    {
        Sparkle sparkle = _shapes[indx];
        sparkle.Y += sparkle.VY;
        sparkle.X += sparkle.VX;
        if (sparkle.Y - (littleCircleHeight / 2) > _rect.Height)
        {
            _shapes.RemoveAt(indx);
        }
        else
        {
            // grab the cached one
            TranslateTransform t = sparkle.Transform as TranslateTransform;
            t.X = sparkle.X - (littleCircle.ActualWidth / 2);
            t.Y = sparkle.Y - (littleCircleHeight / 2);
            _bitmap.Render(littleCircle, sparkle.Transform);
        }
        indx--;

    }

    int x = _random.Next(_bitmap.PixelWidth);
    int y = 0; 

    Sparkle newsparkle = new Sparkle();
    newsparkle.X = x;
    newsparkle.Y = y;
    newsparkle.VX = _random.NextDouble() + .001;
    newsparkle.VX = (_random.Next(10) > 5 ? newsparkle.VX : newsparkle.VX * -1.0);
    newsparkle.VY = _random.NextDouble() * 5 + 1.0;
    newsparkle.Transform = new TranslateTransform() { Y = newsparkle.Y, X = newsparkle.X };

    _shapes.Add(newsparkle);
    _bitmap.Invalidate();
}

Sizing:

void MainPage_SizeChanged(object sender, SizeChangedEventArgs e)
{
    _bitmap = new WriteableBitmap((int)e.NewSize.Width, (int)e.NewSize.Height);
    _bitmap.Clear(Colors.Black);
    _rect = new Rect(0, 0, e.NewSize.Width, e.NewSize.Height);
    dest.Source = _bitmap;
}

The sparkle class:

public class Sparkle
{
    public double X { get; set; }
    public double Y { get; set; }

    public double VX { get; set; }
    public double VY { get; set; }

    public Transform Transform { get; set; }
}

And it also uses a few functions from the WriteableBitmap extension classes on CodePlex.

It doesn’t perform nearly as well as it does in stand-alone Silverlight – but it’s running in a VM on my laptop, without accelerated graphics ….. I blame my hardware.

Finally, someone admits that Silverlight and WPF will (likely) converge

However, will Silverlight and WPF merge?

From Pete Brown:

The Future of Client App Dev : WPF and Silverlight Convergence

As a Microsoft employee (Developer Community Program Manager for Windows Client), he said:

What the Future Holds – Convergence of WPF and Silverlight

 

I recently spoke with Ian Ellison-Taylor at Microsoft. Ian is a General Manager at Microsoft, reporting directly to Scott Guthrie. Among other things, his group handles both Silverlight and WPF (and RIA services and a lot of other stuff). I figured if I wanted the skinny on the future, he’d be the guy to talk to. So, he and I talked about the convergence of Silverlight and WPF, and later exchanged some email on the topic.

 

In the future, it is very likely that both Silverlight and WPF will be a single technology with a single codebase. After all, Silverlight was originally known as WPF/E (E as in Everywhere), and in an amazing 180 degree reversal of our usual approach, we took an ugly codename and created a great product name (Silverlight) from it.

D’uh. Like it wasn’t obvious, especially with the explosive growth and capabilities of Silverlight, why wouldn’t this be on the road map?

Of course, there’s no time frame mentioned, so don’t plan on your Silverlight application being able to use real 3D and actual DataTriggers any time soon.

Impressive Silverlight game engine? Or something else entirely….?

A game in Silverlight – since I can’t read Chinese, I’m not sure what it’s all about, but it looks decent, and doesn’t seem to spike my CPU when playing.

I don’t understand the point of the demo/game that’s there and it seems to be impossibly difficult (as you can see from the screen shot).

Try it here:

http://silverfuture.cn/

image

Found via Silverlike.

As best as I can determine, here are the functions of the various features along the bottom:

image

Update: The comments have a better explanation of what the various items along the bottom do in the “game.”