0 people like it.

Active Pattern Performance with Structs

Demonstrating poor active pattern performance

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
[<Struct>]
type ArrayAsList<'a> =
    val arr : 'a []
    val idx : int
    new (inarr: 'a []) = { arr = inarr; idx = 0 }
    new (inarr: 'a [], inidx: int) = { arr = inarr; idx = inidx }
    member inline t.IsEmpty = t.idx >= t.arr.Length
    member inline t.Head = t.arr.[t.idx]
    member inline t.Tail = ArrayAsList<_>(t.arr, t.idx + 1)

let inline (|EmptyArrayAsList|UnconsArrayAsList|) (all: ArrayAsList<_>) =
     if all.IsEmpty then EmptyArrayAsList else UnconsArrayAsList(all.Head, all.Tail)

let inline (|EmptyArrayAsList'|_|) (all: ArrayAsList<_>) = 
    if all.IsEmpty then Some() else None
     
let inline (|UnconsArrayAsList'|_|) (all: ArrayAsList<_>) = 
    if all.IsEmpty then None else Some(all.Head, all.Tail)

let x_arr = ArrayAsList([|1 .. 10000000|])
let x_list = [1 .. 10000000]

#time

let rec decomposeList l cnt = 
    match l with
    | h :: t -> decomposeList t (cnt + 1)
    | [] -> cnt

decomposeList x_list 0
// Real: 00:00:00.017, CPU: 00:00:00.015, GC gen0: 0, gen1: 0, gen2: 0

let rec decomposeAAL l cnt = 
    match l with
    | UnconsArrayAsList(h, t) -> decomposeAAL t (cnt + 1)
    | EmptyArrayAsList -> cnt

decomposeAAL x_arr 0
// Real: 00:00:00.179, CPU: 00:00:00.171, GC gen0: 85, gen1: 1, gen2: 0

let rec decomposeAAL' (l: ArrayAsList<_>) cnt = 
    if l.IsEmpty then cnt
    else decomposeAAL' l.Tail (cnt + 1)

decomposeAAL' x_arr 0
// Real: 00:00:00.034, CPU: 00:00:00.031, GC gen0: 0, gen1: 0, gen2: 0

let rec decomposeAAL'' l cnt = 
    match l with
    | UnconsArrayAsList'(h, t) -> decomposeAAL'' t (cnt + 1)
    | EmptyArrayAsList' -> cnt
    | _ -> failwith "nope"

decomposeAAL'' x_arr 0
// Real: 00:00:00.183, CPU: 00:00:00.187, GC gen0: 86, gen1: 1, gen2: 0
Multiple items
type StructAttribute =
  inherit Attribute
  new : unit -> StructAttribute

Full name: Microsoft.FSharp.Core.StructAttribute

--------------------
new : unit -> StructAttribute
Multiple items
type ArrayAsList<'a> =
  struct
    new : inarr:'a [] -> ArrayAsList<'a>
    new : inarr:'a [] * inidx:int -> ArrayAsList<'a>
    val arr: 'a []
    val idx: int
    member Head : 'a
    member IsEmpty : bool
    member Tail : ArrayAsList<'a>
  end

Full name: Script.ArrayAsList<_>

--------------------
ArrayAsList()
new : inarr:'a [] -> ArrayAsList<'a>
new : inarr:'a [] * inidx:int -> ArrayAsList<'a>
ArrayAsList.arr: 'a []
ArrayAsList.idx: int
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
val inarr : 'a []
val inidx : int
val t : byref<ArrayAsList<'a>>
member ArrayAsList.IsEmpty : bool

Full name: Script.ArrayAsList`1.IsEmpty
member ArrayAsList.Head : 'a

Full name: Script.ArrayAsList`1.Head
member ArrayAsList.Tail : ArrayAsList<'a>

Full name: Script.ArrayAsList`1.Tail
val all : ArrayAsList<'a>
property ArrayAsList.IsEmpty: bool
property ArrayAsList.Head: 'a
property ArrayAsList.Tail: ArrayAsList<'a>
union case Option.Some: Value: 'T -> Option<'T>
union case Option.None: Option<'T>
val x_arr : ArrayAsList<int>

Full name: Script.x_arr
val x_list : int list

Full name: Script.x_list
val decomposeList : l:'a list -> cnt:int -> int

Full name: Script.decomposeList
val l : 'a list
val cnt : int
val h : 'a
val t : 'a list
val decomposeAAL : l:ArrayAsList<'a> -> cnt:int -> int

Full name: Script.decomposeAAL
val l : ArrayAsList<'a>
active recognizer UnconsArrayAsList: ArrayAsList<'a> -> Choice<unit,('a * ArrayAsList<'a>)>

Full name: Script.( |EmptyArrayAsList|UnconsArrayAsList| )
val t : ArrayAsList<'a>
active recognizer EmptyArrayAsList: ArrayAsList<'a> -> Choice<unit,('a * ArrayAsList<'a>)>

Full name: Script.( |EmptyArrayAsList|UnconsArrayAsList| )
val decomposeAAL' : l:ArrayAsList<'a> -> cnt:int -> int

Full name: Script.decomposeAAL'
val decomposeAAL'' : l:ArrayAsList<'a> -> cnt:int -> int

Full name: Script.decomposeAAL''
active recognizer UnconsArrayAsList': ArrayAsList<'a> -> ('a * ArrayAsList<'a>) option

Full name: Script.( |UnconsArrayAsList'|_| )
active recognizer EmptyArrayAsList': ArrayAsList<'a> -> unit option

Full name: Script.( |EmptyArrayAsList'|_| )
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith

More information

Link:http://fssnip.net/r7
Posted:8 years ago
Author:
Tags: active patterns