This document summarizes Phillip Trelford's talk at the Functional Kats Conference in 2015. It discusses performance comparisons between different programming languages and data structures, including reactive extensions in C# and F# observables. It also covers topics like immutable vs mutable data structures and choosing pragmatic solutions that optimize for speed. Source code examples are provided for concepts like quicksort algorithms and higher-order functions.
6. [Google found that] the page with 10 results took 0.4 seconds to generate. The page
with 30 results took 0.9 seconds. Half a second delay caused a 20% drop in traffic.
Half a second delay killed user satisfaction.
In A/B tests, [Amazon] tried delaying the page in increments of 100 milliseconds
and found that even very small delays would result in substantial and costly drops
in revenue.
Source: http://blog.codinghorror.com/performance-is-a-feature/
10. string a = "abc";
string b = "efg";
string c = "hij";
var d = a + b + c;
string a = "abc";
string b = "efg";
string c = "hij";
var d = new StringBuilder(a);
d.Append(b);
d.Append(c);
string e = d.ToString();
12. type 'a list =
| Empty
| Node of head:'a * tail:'a list
6 2 7 3 nil
13. quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let smallerSorted = quicksort [a | a <- xs, a <= x]
biggerSorted = quicksort [a | a <- xs, a > x]
in smallerSorted ++ [x] ++ biggerSorted
* well it’s short and a sort but it’s not
quick!
Source: http://learnyouahaskell.com/recursion
14. “people are too puritanical about purity”
- Jon Harrop on Quora
16. Higher –order functions
Directory.GetFiles(path)
|> Seq.map FileInfo
|> Seq.map (fun x -> x.Name, x.Length)
Query expression
query {
for file in Directory.GetFiles(path) do
let info = FileInfo(file)
select (info.Name, info.Length)
}cSequence comprehension
seq {
for file in Directory.GetFiles(path) ->
let info = FileInfo(file)
info.Name, info.Length
}
17.
18. LinqOptimizer compiles declarative
LINQ queries into fast loop-based
imperative code. The compiled code
has fewer virtual calls and heap
allocations, better data locality and
speedups of up to 15x
19.
20.
21.
22. Reactive Extensions (C#) F# Observable module Nessos Streams
let rxValue =
data
.ToObservable()
.Where(fun x -> x%2L = 0L)
.Select(fun x -> x * x)
.Sum()
.ToEnumerable()
|> Seq.head
// Real: 00:00:02.895,
CPU: 00:00:02.843,
GC gen0: 120, gen1: 0, gen2: 0
let obsValue =
data
|> Observable.ofSeq
|> Observable.filter (fun x -> x%2L = 0L)
|> Observable.map (fun x -> x * x)
|> Observable.sum
|> Observable.first
// Real: 00:00:00.479,
CPU: 00:00:00.468,
GC gen0: 18, gen1: 0, gen2: 0
let streamValue =
data
|> Stream.ofArray
|> Stream.filter (fun x -> x%2L =
0L)
|> Stream.map (fun x -> x * x)
|> Stream.sum
// Real: 00:00:00.130,
CPU: 00:00:00.109,
GC gen0: 0, gen1: 0, gen2: 0
23. Be scientific
Do test multiple implementations
Don’t set out to confirm your bias
Instrument and profile your code
26. HybridDictionary attempts to optimize
Hashtable.
It implements a linked list and hash
table data structure, switching over to
the second from the first when the
number of elements increases past a
certain threshold.
https://www.simple-talk.com/blogs/2011/10/21/some-non-generic-collections/
33. Prefer safe and simple defaults - immutability
Assume nothing – profile everything
Mutable arrays are fast
Build fast data structures from arrays
Be pragmatic and they’ll be your friend
C/C++ & Scala have extensive mutable data structure libraries
Selecting appropriate data structures is key to your application's performance. In this session we'll go beyond lists to find orders of magnitude performance improvements. Expect plenty of live demos and anecdotes gathered over decades of financial and AAA video game development.
http://c2.com/cgi/wiki?GreencoddsTenthRuleOfProgramming
"Every sufficiently complex application/language/tool will either have to use a database or reinvent one the hard way.“
http://c2.com/cgi/wiki?GreenspunsTenthRuleOfProgramming
Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of CommonLisp.