Monday, July 16, 2007

Recent Mono / MS JIT observations with #64

Some time ago, I had run #64 using the Mono and MS runtimes.  Judging on the timeframe of my post, I expect I was running version 1.2.3.

Everything worked great; however, there was a fairly significant delta in performance between the two, Mono falling quite short of the MS runtime. It didn't concern me at all, as the emulator was still running at 100% the performance of the original C64.

I am now running version 1.2.4.

I ran the emulator under both runtimes for about 90 seconds, and monitored the CPU usage under the Performance Monitor.  I started monitoring after the emulator had fully started up, to exclude JIT overhead.


Command Line CPU Usage (%)
Average Minimum Maximum
mono TestHost.exe 38.813 29.687 67.187
TestHost.exe 45.229 21.875 59.375

Granted, these tests aren't entirely scientific, but for 90 seconds, the average is quite different, in Mono's favour.

Could the recent patches to the MS runtime be causing the drop in performance?

UPDATE:

Turns out that my machine was set 'Maximum Battery' mode.  In 'Maximum Performance' mode.  I wonder why Mono performs better in this scenario?

When reverted to 'Maximum Performance', the CPU usage of Mono didn't change (~38%) and is fairly consistent:

image 

whereas the MS JIT jumps from 20% to 40% in cycles, as follows.

image_3 

Each vertical line represents 4 seconds.

Wednesday, July 11, 2007

Google Bookmarks 'bookmarklet' link in Safari

If you are unable to use the Google Bookmarks 'bookmarklet' in Safari, the workaround is to manually add a bookmark and use the following javascript code for the address.

javascript:(function(){a=window;b=document;c=encodeURIComponent;d=a.open("http://www.google.com/bookmarks/mark?op=edit&output=popup&bkmk="+c(b.location)+"&title="+c(b.title),"bkmk_popup","left="+((a.screenX||a.screenLeft)+10)+",top="+((a.screenY||a.screenTop)+10)+",height=420px,width=550px,resizable=1,alwaysRaised=1");a.setTimeout(function(){d.focus()},300)})();
The issue is the spaces and quotes in the original javascript code do not appear to be correctly decoded in Safari.

Tuesday, May 15, 2007

Mono 1.2.4 released

According to the Mono Project feed, Mono 1.2.4 has been released.  Check out the link as there are lots of improvements.

GraphicsDeviceCapabilities.CompareCaps

Implemented CompareCaps a few days ago, which are exposed via the AlphaCompareCapabilities and DepthBufferCompareCapabilities.  These indicate the comparison operators supported for the alpha and depth buffers.  Their OpenGL equivalents are glAlphaFunc and glDepthFunc respectively.

The implementation was easy, since they were all supported since v1.0 of OpenGL and therefore just return true.

As per MSDN documentation,

Represents comparison capabilities.

Property OpenGL Extension or Minimum Version
SupportsAlways v1.0
SupportsEqual v1.0
SupportsGreater v1.0
SupportsGreaterEqual v1.0
SupportsLess v1.0
SupportsLessEqual v1.0
SupportsNever v1.0
SupportsNotEqual v1.0

MonoXna - what version of OpenGL?

A few posts on the MonoXna groups generated an interesting discussion related to implementing the GraphicsDeviceCapabilities API.  What is the minimum version of OpenGL we should (or even can) support?

There will be a number of features expected of the base Xna implementation, which will not be available in earlier versions of OpenGL. 

So far, from what I can tell we will need

  • v1.5 with a significant set of ARB/EXT extensions
  • 2.0 with the pixel buffer, and a few other ARB/EXT extensions
  • 2.1+

Should we go straight for 2.0 or try to target 1.5?

Monday, May 14, 2007

Altap Salamander 2.5 has been released

I am a long time user of Orthodox File Managers, which can generally be categorised as a two pane view of a hierarchical storage system.  Examples of these include file, registry, archive (zip, rar, etc) ftp, nfs, etc.  I used Far for some time, which has a fantastic plug-in model, but was not progressing.  I changed to Salamander 2.5 Beta well over a year ago, and have never looked back.  Now that it has been released, you can pick it up for $30 USD.

Whilst Far is somewhat nostalgic of DOS file managers, like Norton and XTree, we live in a world of WYSIWYG, and I find character mode doesn't cut it when previewing files.  This is where the move to Salamander was welcomed.  It's still missing features a loved in Far, but if Altap ever release their SDK, I'll be the first to jump in.

image01 

For OSX I have been experimenting with Disk Order 2.5 - it still has a ways to go, lacking many of the standard key strokes one expects from a 2 pane file manager, but is by far the best option on the Apple platform today.

image05

Monday, May 07, 2007

Tao 2.0 and SDL.NET 6.0 released

Great to see that Tao 2.0 and SDL.NET 6.0 were released over the weekend. 

The pre-release versions are currently in use by MonoXna, so I look forward to updating to the released versions as soon as possible.

Friday, May 04, 2007

GraphicsDeviceCapabilities.AddressCaps structure

As per MSDN documentation,

Represents the texture addressing capabilities for Texture structures

There are 6 capabilities for this structure, as follows

Property OpenGL Extension or Minimum Version Notes
SupportsBorder
GL_ARB_texture_border_clamp
Gets a value indicating whether the device supports the setting of coordinates outside the range [0.0, 1.0] to the border color.
SupportsClamp
GL_EXT_texture_edge_clamp
Gets a value indicating whether the device supports the clamping of textures to addresses.
SupportsIndependentUV
Unknown Gets a value indicating whether the device can separate the texture-addressing modes of the texture's u and v coordinates.
SupportsMirror
GL_EXT_texture_mirror_clamp
Gets a value indicating whether a device can mirror textures to addresses.
SupportsMirrorOnce
GL_EXT_texture_mirror_clamp
+
GL_ATI_texture_mirror_once
Gets a value indicating whether a device can take the absolute value of the texture coordinate (thus, mirroring around 0) and then clamp to the maximum value.
SupportsWrap
Unknown Gets a value indicating whether a device can wrap textures to addresses.

If these are not correct or you can help fill in the blanks, comments are welcome.

GraphicsDeviceCapabilities and OpenGL

Part of the process of implementing GraphicsDevice and GraphicsAdapter involve a number of related classes.  The first I'm going to tackle is GraphicsDeviceCapabilities.

As per the MSDN documentation, this class represents the capabilities for the hardware.  It is made up of no less than 18 structures, defined with the GraphicsDeviceCapabilities class definition.  I expect I may run in to a few cross platform issues whilst implementing some of the queries, so it will be an interesting exercise.

Over the coming days / weeks / whenever, I'm going to document each structure as a separate article and on the Mono.XNA groups as to how I've obtained the capabilities, with references to articles, etc - hopefully garnering feedback from the Mono.XNA team and other OpenGL / DirectX experts.

I've also created a page on the mono.xna discussion group, to track and document our implementation of the various GraphicsDeviceCapabilities structures.

Thursday, May 03, 2007

C# partial classes and file naming conventions

I find that partial classes in C# have more uses than just the automatic .Designer.cs created by numerous designers in your IDE of choice.

In certain scenarios, I will create partial classes and use multiple files.  I consider the [Class Name].cs as the primary file and [Class Name].[Name].cs as the satellite files.  The name is up to you, but should succinctly indicate the function and preferrably is one word.

I've found in practice it has worked very well, with regards to maintenance and reducing the time to understand a class.  I've been using this convention for a while, and felt it was time to review, given a few ideas I've been tossing around.

Currently I only use it for classes that are large enough to warrant separating out functional areas.  Additionally, if the class implements a complex interface or a related set of interfaces I may move these to a separate file.

I consider this is appropriate for larger classes and therefore you would always start off with a single file and as your implementation grows, reconsider if it is worth separating.

  • Limiting the public interface of the class to the primary file, so it is very easy for a developer to view the file and determine the public API
    • Move protected and private members to a separate file
      • [Class Name].private.cs
    • When a class has a significant number of private and protected members, separate as
      • [Class Name].private.cs
      • [Class Name].protected.cs

I know regions can provide similar functionality, assuming your editor supports outlining, but I tend to see them either overused or not at all.  When viewing a file in [insert simple text viewer of your choice], regions provide little value.

I usually limit regions to:

#region private fields
#region constructors
#region public members
#region protected members
#region private members

Thoughts?

Wednesday, May 02, 2007

GamePad and Color implementations for Mono XNA

Just posted some updates to the repository tonight, now that I have write access.  This is really going to help me, in moving things along whilst I have a little time to contribute right now.

  • GamePad
    • As previously mentioned, GamePad has a preliminary implementation of the two dead zone algorithms now
    • Unit tests (where possible) have also been submitted
  • Color
    • The initial source appeard to come from the System.Drawing namespace in the mono implementation of the BCL, so it was a little heavy for XNA.  I've submitted a revised versions that is greatly simplified and is now 100% complete, with associated unit tests.
    • These unit tests helped me figure out a few things about the MS implementation, including the fact that Vector3 / Vector4 conversions use rounding rather than truncation.

I've started work on GraphicsDevice and Graphics adapter, but these will require acquiring a more thorough knowledge of OpenGL.  To assist with this process, I've ordered the Red Book and OpenGL Distilled

Update: I've added the OpenGL: Reference Manual to that order

I'll post some discovery in the coming days.

Monday, April 30, 2007

GamePad Dead Zone functionality

The last couple of nights I've been working on the dead zone functionality for the GamePad class in MonoXna, which was an interesting excursion off into formula's and equations I haven't been exposed to for many years.

I read an post by Shawn Hargreaves, which gave me a good start on understanding the MSXNA implementation.  I've now implemented the basic functionality of the two algorithms, IndependentAxis and Circular.

I used Shawn's formula for the IndependentAxis deadzone calculation and here is a plot of this:

Independent Axis - Plot X Independent Axis - Plot XY
IndependentAxisPlotX4  IndependentAxisPlotXY1 

I ended up using a variation of Shawn's formula for the IndependentAxis and using a bit of trig, ended up with the following for the Circular implementation:

/// <summary>
/// As per http://blogs.msdn.com/shawnhar/archive/2007/03/28/gamepads-suck.aspx
/// Both <paramref name="x"/> and <paramref name="y"/> parameters assumed to be between -1.0 and 1.0
/// </summary>
static Vector2 CircularAxisDeadZone(float x, float y)
{
    float dist = (float)Math.Max(Math.Sqrt(x * x + y * y), EPSILON);
    float deadZone = Math.Max(dist - DEADZONE, 0)/(MAX_DIST - DEADZONE)/dist;
    return new Vector2(x*deadZone, y*deadZone);
}

The MSDN documentation states that the Circular algorithm uses the combined position of both joystick axes to make the deadzone calculation.  So,

  1. We calculate the distance from the centre, and if zero, returning EPSILON, so we never divide by zero.
  2. If we're in the DEADZONE (=0.2f), we'll clamp to 0, otherwise we'll create a weighting factor for the deadzone calculation
  3. return a Vector2 with the new x,y values

Here is a plot of our IndependentAxis calculation:

Circular - Plot XY
CircularPlotXY1 

Monday, April 23, 2007

#64 - Commodore 64 emulator on Mono

With the recent success of running Pong on Mono.Xna, on the mono runtime, I decided to try my port of #64.  I was pleasantly surprised to see it run without recompilation or any issues on the mono runtime.

My first observation was the not insignificant increase in CPU usage over running on the Microsoft JIT. 

I haven't had a chance to dig into things yet, and it may not be for a while, some areas I will look at are:

  • switch statements
    • Like many emulators, #64 has a number of large switch statements to emulate the various CPUs (6502, 6510, 6581, 6569, etc), and these are perhaps not as well optimized as the MS JIT.
  • inlining
    • Whilst I inlined some code, the other possibility is that the mono JIT may not be as aggressive when inlining code.
  • floating point
    • The sound emulation does use a significant amount of floating point code.
  • memory allocation
    • I am pretty sure the memory allocation is minimal, and suspect the mono memory allocator is just a pointer being incremented, much like the MS implementation 

It will be an interesting journey into the inners of the code generation and optimizations, since I'm not familiar with all the optimization techniques.  I'll blog about my experiences when the time comes.

Thursday, April 19, 2007

Running Pong under Mono.Xna on mono

It is official; we've successfully run Pong under Mono.Xna!  It is running with either the Microsoft or mono runtimes!

Last night, I completed most of the core functionality within the Microsoft.Xna.Framework.Game.dll assembly, and wrote a number of unit tests to exercise the Game logic.

Looks and runs identical to it's counterpart running under the Microsoft implementation of Xna.

PongFirstRun3 

My next step is to run it under the mono runtime on my windows machine and then follow with running it on my MacBook Pro.  This is completed.  Now for my Macbook Pro.

I will submit patches after I complete the additional classes I stubbed to get this basically working.

Tuesday, April 17, 2007

Mono.Xna - The beginning

Why?

Given my interest in game programming, graphics and generally making computers do interesting things other than running enterprise software, I've starting contributing to the mono.xna team.

These series of posts, tagged with XNA, will chronicle my findings, exploration and implementation of my areas of the XNA framework.

Hardware and Development

I own a Macbook Pro and a Windows laptop, so I can develop and test on both these platforms.  My primary development environment will be VS 2005, since I cannot live without Resharper 2.5, and think any serious software engineer should at least look at this tool.

And it begins...

After I obtained the current code, I found the best place to start was implementing the classes in Microsoft.Xna.Framework.Game.dll, since this assembly was largely unimplemented, and is really one of the core entry points for a consumer of this framework.

Based on previous conversations in the discussion group, Tao and SDL.NET are the cross-platform APIs of choice.  This was great to see, given I've previously used and contributed to SDL.NET for my C# implementation of the Frodo C64 emulator, and found it easy to use.

Wednesday, April 04, 2007

Command Prompt : Set the title for easier ALT-TAB

If you are like me, and run several command prompts at any given time, rooted at different folders, it turns into a game of chance, when 'ALT-TAB'ing. "Visual Studio 2005 Command Prompt" is a little too generic.

I'm in the habit of using the title command to use something more meaningful:

Sunday, March 25, 2007

Generic copy object using Lightweight Code Generation

I was involved in a discussion on microsoft.public.dotnet.framework.clr regarding reflection and lightweight code generation. The original topic was in regards to a 2x slowdown using reflection in .NET 2.0 over 1.1, which was ultimately recognised as a bug by the Microsoft CLR team. I brought up the possibility of using LCG as an alternative in 2.0, and the one of the contributers presented some good examples of using Delegate.CreateDelegate. Here I wanted to present a use of LCG to copy all the public read/write properties of any object. The meat of the example was the GenerateCopyDelegate function, as follows:
static CopyPublicPropertiesDelegate<T> GenerateCopyDelegate<T>()
{
    Type type = typeof(T);
 
    DynamicMethod dm = new DynamicMethod(type.Name, null, new Type[] { typeof(T), typeof(T) }, typeof(Program).Module);
 
    ILGenerator il = dm.GetILGenerator();
 
    PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
 
    foreach (PropertyInfo prop in props)
    {
        if (prop.CanRead && prop.CanWrite)
        {
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldarg_0);
            il.EmitCall(OpCodes.Callvirt, prop.GetGetMethod(), null);
            il.EmitCall(OpCodes.Callvirt, prop.GetSetMethod(), null);
        }
    }
    il.Emit(OpCodes.Ret);
 
    return (CopyPublicPropertiesDelegate<T>)dm.CreateDelegate(typeof(CopyPublicPropertiesDelegate<T>));
}

 

Method Calls (per iteration) Total Calls
Delegate get_* set_*
LCG 1 6 6 13,000,000
Delegate 12 6 6 24,000,000

Monday, March 19, 2007

A simple console logger

A very simple class for logging output to the console. What's special about it?
  • Intended for the console only.
    • I wanted to keep the code very simple.
  • Uses colour to differentiate the log message based on type: INFO, WARN or ERROR.
  • Supports immediate or buffered output
    • All colour output is honoured in buffered mode.
    • Use Logger.Flush() to display pending output.
Get it here.

A better FindControl: FindControlOf<T>

Whilst helping a colleague with some ASP.NET questions, I found a number of blocks enumerating the Controls collection for specific control types. Having to enumerate and determine the control type can become quite tedious, so I provided an iterator to simplify:

   1:  static IEnumerable FindControlsOf<T>(Control parent)
   2:      where T : class
   3:  {
   4:      foreach (Control control in parent.Controls)
   5:      {
   6:          T item = control as T;
   7:          if (item != null)
   8:          {
   9:              yield return item;
  10:          }
  11:   
  12:          // Don't enumerate the children, if control is type T as an optimization, since our
  13:          // typical search criteria is not container controls.  If the criteria changes, 
  14:          // remove the "item == null" check.
  15:          if (item == null && control.Controls.Count > 0)
  16:          {
  17:              foreach (T child in FindControlsOf<T>(control))
  18:              {
  19:                  yield return child;
  20:              }
  21:          }
  22:      }
  23:  }


Making it easy to enumerate controls of a specific type:

   1:  foreach (MyControl sa in FindControlsOf<MyControl>(pnlMyContainer))
   2:  {
   3:      ...
   4:  }


I should point out that this code generates recursive state machines depending on the depth of the hierarchy of controls, so it should be used carefully.