I put together a small snippet to help out with making performance metrics. You can find it here. Feel free to fork it and change it to your needs - and post live code snippets on further topics or comments.

What I see on basic arrays is that they are indeed pretty slow, I get 1M entries sorted in just over a second on my machine - here is the direct link.

You can check the proxy implementation here, suggest improvements or submit a PR - help is always appreciated.

By on 5/7/2016 6:00 AM ()

Thank you for the sample code.

I modified it to be representive of the sortBy issue that I am having.

This link should work now.

I look forward to the performance improvement in the future version.

Any suggestions to speed it up would be appreciated. Note that this code is several orders of magnitude slower that a simple Array.sortBy lambda implementation. I can hear my computer's fan kick in when I run this example.

By on 5/11/2016 4:23 PM ()

Hello,

thanks for your testing. Current Array.sortBy proxy quite bad, sorry. It recalculates the mapping on every comparison, and also, does not take indexes into account, so it can mess up ordering between elements with identical key (.NET Array.sortBy preserves it).

My suggestion would be to use a Direct function for now if you need better performance:

1
2
3
4
5
6
7
8
9
10
11
12
13
[<Direct "
    $arr.map(function (a, i) {
        return [a, $f(a), i];       
    }).sort(function(a, b) {
        var av = a[1], bv = b[1];
        if (av !== bv) {
            if (av > bv) return 1;
            return -1;
        }
        return a[2] - b[2];
    }).map(function (a) { return a[0]; })
    ">]
let sortBy (f: 'a -> 'b) (arr: 'a[]) = X<'a[]>

We will review all collection functions for a next release of WebSharper.

For question 2.: Sorry, what do you mean by mutable list? In general, you can aceess underlying JavaScript functionality with the .JS extension property, so if you have an array: arr.JS.Shift("new item") will append an element to the beginning of it, just beware that it breaks .NET semantics, changes a length of a value that is typed 'a[].

For question 3.: We don't have a built-in way of measuring translated code performance yet. We are currently preparing a new major release of WebSharper where we will focus on performance more.

Now, you can use an inline to get a high resolution timestamp:

1
2
[<Inline "performance.now()">]
let performanceNow() : X<float>
By on 5/7/2016 2:51 AM ()

question 2:

I would like to write FSharp code whenever possible. So I want code some code that might look like this

let mutable = result for i in collection do result <- (f i) :: result
result <- List.rev result

I would like to know if there is a better way without directly referencing JS constructs.

By on 5/11/2016 4:27 PM ()

Why not write Seq.map f collection?

By on 5/11/2016 6:57 PM ()

The primary reason was that I was doing several other operation and then appending. So something like this

1
2
3
4
5
6
7
8
9
10
let foo (tasks : seq<_>) = 
   async
   {
     let globalItems = ref []
     for t in tasks do
       let! localItems = Server.MyRPC t
       for i in localItems do
         .. update DOM ..
         globalItems := i.point :: !globalItems
   }

The primary question was "is there is a better F# data structure for this?" I would have normally used System.Collections.Generic.List<_>, but I assume that the proxy wouldn't map well to javascript, which is an incorrect assumption. System.Collections.Generic.List<_> is an order of magnitude faster than list appends.

This isn't a question; it is an answer for others who are curious.

By on 5/14/2016 6:39 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper