Again, I’d like to thank Igal Tabach­nik and SharpCrafters for invit­ing me to do the webi­nar, the record­ing of the ses­sion is now avail­able on their Vimeo channel.

Pseudo Real Time Per­for­mance Mon­i­tor­ing with AOP and AWS Cloud­Watch from SharpCrafters on Vimeo.

 

Per­for­mance Mon­i­tor­ing with AOP and Ama­zon Cloud­Watch

View more Pow­er­Point from Yan Cui

 

Source code is avail­able at http://aop-demo.s3.amazonaws.com/RTPerfMonDemo.zip

Share

To find the answer to this ques­tion I put together a very sim­ple test, but before we go into it..

Dis­claimer: this test and its result should be taken at face value only, it is intended to illus­trate that post­ing mes­sages to an agent is super light­weight, but in a real world appli­ca­tion there will be many other con­straints and con­sid­er­a­tions (such as latency, etc.) that should be taken into account before you decide to use F# agent instead of other alternatives.

 

So, back to the test itself, here’s the test code:

image

the line that posts 30 mil­lion mes­sages (4 byte inte­gers in this case) to the agent returned in 0.983 sec­ond, but the agent actu­ally took just over 12 sec­onds to receive and process all the messages.

Suf­fice to say that in most cases try­ing to get mes­sages to a F# agent is unlikely to be the bot­tle­neck in your sys­tem at a solid 30 mil­lion mes­sages a second Winking smile

How­ever, pro­cess­ing of those mes­sages takes sig­nif­i­cantly longer, and if the back­log con­tin­ues to build then even­tu­ally you will be hit with an Out­OfMem­o­ryEx­cep­tion. Also, if you’re depend­ing on a sync/async reply from the agent, latency can also be a big prob­lem if the agent is allowed to build up a huge back­log of mes­sages. Keep these in mind when you’re design­ing your appli­ca­tion around F#’s agents.

 

Finally, for the ques­tion of ‘how many mes­sages can you post to a F# agent in one sec­ond?’, on my Corei7 3.3GHz, the answer is a cool 30 mil­lion Smile

Share

One of the prob­lems with using F#’s Dis­crim­i­nated Unions is that they are not exten­si­ble, in that all your union cases must be spec­i­fied inside one Dis­crim­i­nated Union (abbre­vi­ated to DU from this point) type and you can’t inherit from an exist­ing DU type to add addi­tional union cases.

In most cases, hav­ing to spec­ify all your union cases inside one DU type makes per­fect sense and I’m sure there is a very good rea­son for the lan­guage design­ers to not allow inher­i­tance with DU types.

How­ever, some­times I do find myself wish­ing for some exten­si­bil­ity so that I can keep using DU types instead of hav­ing to revert back to a com­plex class hierarchy.

Sup­pose you have a mes­sag­ing appli­ca­tion, you can define the dif­fer­ent types of mes­sages your sys­tem under­stands as a DU:

image

How­ever, as the appli­ca­tion grows you might want to add more spe­cial­ized types of mes­sages, and you don’t want to add them to Mes­sageTypes to stop it from becom­ing bloated and to keep the spe­cial­ized mes­sage types closer to code that actu­ally under­stand them.

So what do you do in that case? Go back to using a class hier­ar­chy? Sure, that’s one approach.

Another approach to this prob­lem is to use marker inter­faces, so the above code becomes:

image

The fact that DU types can imple­ment inter­faces is often over­looked but you can make good use of it here to enable some exten­si­bil­ity to your DU types.

Notice how the func­tion f is changed from pat­tern match­ing the union cases to pat­tern match­ing against the type of the mes­sage (sim­i­lar to how you can use pat­tern match­ing in a try-with block) before pass­ing the mas­sage to the appro­pri­ate han­dler func­tion that under­stands that spe­cific type.

 

Well, thank you for read­ing and hope this post proves to be help­ful to you Smile

Share

Fol­low­ing my recent webi­nar with SharpCrafters on how to setup pseudo real-time per­for­mance mon­i­tor­ing using Aspect Ori­ented Pro­gram­ming and Ama­zon Cloud­Watch, I’d like to say thanks to the guys for hav­ing me, it was a great fun Smile

For any­one inter­ested, the source code is avail­able at:

http://aop-demo.s3.amazonaws.com/RTPerfMonDemo.zip

If you want to run the demo con­sole app to gen­er­ate some data, you need to put your AWS key and secret in the App.config file in the Demo.ConsoleApp project:

image

Just go to aws.amazon.com and cre­ate an account, you’ll then be given an access key and secret to use.

The slides for the ses­sion is also avail­able to down­load on SlideShare:

Enjoy!

Share

I love using F#’s Record and Dis­crim­i­nated Union types, they work nicely with pat­tern match­ing inside your F# code and can often alle­vi­ate some of the cer­e­mony involved around cre­at­ing and using a com­plex object hierarchy.

How­ever, on the odd occa­sion when you need to seri­al­ize them into JSON/XML/Binary for­mat, it might not be imme­di­ately obvi­ous what you need to do to achieve that goal.

In gen­eral, I avoid using F# spe­cific types when I require inter­op­er­abil­ity with C# and/or sup­port for trans­port as it’s just much more eas­ily done with stan­dard CLR types. How­ever, in case that’s not an option, I hope this post will give you a sum­mary of the dif­fer­ent ways you can pre­pare your Record/DU types for transport.

Record

To seri­al­ize a Record type using the Dat­a­Con­tract­Se­ri­al­izer (for XML) or Dat­a­Con­trac­tJ­son­Se­ri­al­izer (for JSON), sim­ply dec­o­rate your Record type with Dat­a­Con­trac­tAt­tribute and DataMem­ber­At­tribute like you nor­mally would:

image

After that you can serialize/deserialize a Per­son instance nor­mally although the seri­al­ized XML/JSON would not be as read­able as with other CLR types:

JSON

Record:

{“Age@”:99,“Name@”:“Yan Cui”}

Class:

{ “Age” : 99, “Name” : “Yan Cui” }

XML

Record:

<FSI_0002.Person xmlns=”http://schemas.datacontract.org/2004/07/”

                            xmlns:i=“‘http://www.w3.org/2001/XMLSchema-instance”>

    <Age_x0040_>99</Age_x0040_>

    <Name_x0040_>Yan Cui</Name_x0040_>

</FSI_0002.Person>

Class:

<Per­son xmlns=”http://schemas.datacontract.org/2004/07/ClassLibrary1”

             xmlns:i=“http://www.w3.org/2001/XMLSchema-instance”>

    <Age>99</Age>

    <Name>Yan Cui</Name>

</Person>

As for binary seri­al­iza­tion, a Record type is marked with the Seri­al­iz­able attribute by default, which means it can be seri­al­ized with the Bina­ry­For­mat­ter. This is how the Per­son record type looks in reflector:

image

Dis­crim­i­nated Unions

A sin­gle case Dis­crim­i­nated Union such as the one below is seri­al­iz­able by Dat­a­Con­tract­Se­ri­al­izer, Dat­a­Con­trac­tJ­son­Se­ri­al­izer and Bina­ry­For­m­mat­ter out of the box.

image

The JSON and XML out­put for an instance of this DU looks like this:

JSON :

{“item”:“test”}

XML   :

<Sin­gle­CaseDU xmlns=”http://schemas.datacontract.org/2004/07/”

                        xmlns:i=“http://www.w3.org/2001/XMLSchema-instance”>

    <item>test</item>

</SingleCaseDU>

A multi-case Dis­crim­i­nated Union on the other hand, requires a lit­tle more work.

image

Whilst it works with Bina­ry­For­mat­ter by default, it will not with Dat­a­Con­tract­Se­ri­al­izer and Dat­a­Con­trac­tJ­son­Se­ri­al­izer. If you try to seri­al­ize an instance of Mul­ti­Cas­eDU using either you will get a Seri­al­iza­tionEx­cep­tion say­ing that the type MultiCaseDU.Case1 or MultiCaseDU.Case2 is not expected.

So to make the Mul­ti­Cas­eDU type seri­al­iz­able with both Dat­a­Con­tract­Se­ri­al­izer and Dat­a­Con­trac­tJ­son­Se­ri­al­izer you need to sup­ply the nested types (Case1 and Case2) to the known type resolver. Some­thing like this would do the trick:

image

After that, you’ll be able to seri­al­ize instances of Mul­ti­Cas­eDU:

JSON

Case1:

{“__type”:“MultiCaseDU.Case1:#FSI_0002.Contracts”,“item”:“test”}

Case2:

{“__type”:“MultiCaseDU._Case2:#FSI_0002.Contracts”}

XML

Case1:

<Mul­ti­Cas­eDU i:type=“MultiCaseDU.Case1”

                     xmlns=”http://schemas.datacontract.org/2004/07/”

                     xmlns:i=“http://www.w3.org/2001/XMLSchema-instance”>

    <item>test</item>

</MultiCaseDU>

Case2:

<Mul­ti­Cas­eDU i:type=“MultiCaseDU._Case2”

                     xmlns=”http://schemas.datacontract.org/2004/07/”

                     xmlns:i=“http://www.w3.org/2001/XMLSchema-instance”/>

 

 

 

For the full exam­ple, includ­ing seri­al­iza­tion and dese­ri­al­iza­tion code, see this gist.

Share