6.5 FParsec.StaticMapping
This module defines functions for creating optimized mapping functions between keys and values.
This module is not available in the Low‐Trust version of FParsec.
6.5.1 Interface
// FParsec.dll namespace FParsec type Range = struct new: min: int * max: int -> Range val Min: int val Max: int end module StaticMapping = val createStaticCharIndicatorFunction: invert: bool -> charsInSet: seq<char> -> (char -> bool) val createStaticCharRangeIndicatorFunction: invert: bool -> rangesInSet: seq<Range> -> (char -> bool) val createStaticIntIndicatorFunction: invert: bool -> valuesInSet: seq<int> -> (int -> bool) val createStaticIntRangeIndicatorFunction: invert: bool -> rangesInSet: seq<Range> -> (int -> bool) val createStaticIntMapping: defaultValue: 'T -> keyValues: seq<int*'T> -> (int -> 'T) val createStaticIntRangeMapping: defaultValue: 'T -> keyValues: seq<Range*'T> -> (int -> 'T) val createStaticStringMapping: defaultValue: 'T -> keyValues: seq<string*'T> -> (string -> 'T)
6.5.2 Remarks
The functions in the StaticMapping
module use runtime code generation via System.Reflection.Emit
to create optimized mapping functions between keys and values.
Runtime code generation is relatively expensive, so the functions in this module should only be used for optimizing static mappings that are potentially called a (very) large number of times.
The code generated for the optimized mapping functions will occupy memory until the associated AppDomain is unloaded.
The performance of the generated functions depends a lot on the individual key‐value mapping and the application‐specific call pattern. Ignoring the overhead of the function call, the generated mapping functions should generally be as fast as an equivalent statically compiled switch‐statement in C# or F#. In certain cases they will even be faster.
The code size of the generated functions increases about linearly with the number of key ranges (i.e. continuous sequences of keys with the same
value). Hence, you should only use the StaticMapping
module for small mappings. If you try
to turn arbitrarily large key‐value mappings into static mapping functions, you’ll likely hit upon certain implementation limitations (of this
module’s code, of Reflection.Emit
or of the
CLR’s JIT).
If the conditional compilation symbol DEBUG_STATIC_MAPPING
is defined when compiling FParsec, the generated
mapping functions will compute each result with two different methods and check the results against each other. Of course, this means that they
will take more than twice the time than without the DEBUG_STATIC_MAPPING
symbol and will also consume more memory. In Debug builds of FParsec DEBUG_STATIC_MAPPING
is switched on by default, since the StaticMapping
module is still relatively new.
Measuring and comparing the performance of the generated mapping functions only makes sense in Release builds.
6.5.3 Members
type Range
Represents an immutable range between the integer values Min
and Max
(inclusive).
type Range = struct new: min: int * max: int -> Range val Min: int val Max: int end
The Min
value must not be larger than the Max
value. In a Debug build this condition is checked by an assert‐check in the Range
constructor.
val createStaticCharIndicatorFunction: invert: bool -> charsInSet: seq<char> -> (char -> bool)
Creates an optimized indicator function for the chars specified by the charsInSet
sequence.
If invert
is false
(true
), the returned indicator function will return true
(false
) if and only if it is called with a char contained
in charsInSet
.
charsInSet
may contain duplicate char values.
Internally, this function collects continuous ranges of chars into Range
values and then uses the same compilation strategy as createStaticCharRangeIndicatorFunction
.
Please also see the remarks at the beginning of this section.
val createStaticCharRangeIndicatorFunction: invert: bool -> rangesInSet: seq<Range> -> (char -> bool)
Creates an optimized indicator function for the chars in the ranges specified by the rangesInSet
sequence.
If invert
is false
(true
), the returned indicator function will return true
(false
) if and only if it is called with a char contained
in at least one of the ranges of rangesInSet
.
rangesInSet
may contain overlapping or duplicate ranges. However, the ranges must not
contain values less than 0
or greater than 0xffff
(the minimum and maximum UTF‐16 char values), otherwise an ArgumentException
is
thrown.
Please also see the remarks at the beginning of this section.
val createStaticIntIndicatorFunction: invert: bool -> valuesInSet: seq<int> -> (int -> bool)
Creates an optimized indicator function for the integers specified by the valuesInSet
sequence.
If invert
is false
(true
), the returned indicator function will return true
(false
) if and only if it is called with an integer
contained in valuesInSet
.
valuesInSet
may contain duplicate integer values.
Internally, this function collects continues ranges of integer into Range
values and then uses the same compilation strategy as createStaticIntRangeIndicatorFunction
.
Please also see the remarks at the beginning of this section.
val createStaticIntRangeIndicatorFunction: invert: bool -> rangesInSet: seq<Range> -> (int -> bool)
Creates an optimized indicator function for the integers in the ranges specified by the rangesInSet
sequence.
If invert
is false
(true
), the returned indicator function will return true
(false
) if and only if it is called with an int
contained in at least one of the ranges of rangesInSet
.
rangesInSet
may contain overlapping or duplicate ranges.
Please also see the remarks at the beginning of this section.
val createStaticIntMapping: defaultValue: 'T -> keyValues: seq<int*'T> -> (int -> 'T)
Creates an optimized mapping function that maps integer keys to values.
The keyValues
sequence specifies the key‐value pairs for the mapping. All keys not
specified in keyValues
are mapped to defaultValue
.
This function throws an ArgumentException
if keyValues
contains a duplicate key.
Internally, this function collects continues ranges of integer keys with equal values[1] into Range
values and
then uses the same compilation strategy as createStaticIntRangeMapping
.
Please also see the remarks at the beginning of this section.
Creates an optimized mapping function that maps integer key ranges to values.
The keyValues
sequence specifies the range‐value pairs for the mapping. All keys not
contained in one of the ranges in keyValues
are mapped to defaultValue
.
This function throws an ArgumentException
if keyValues
contains an overlapping or
duplicate key range.
Please also see the remarks at the beginning of this section.
val createStaticStringMapping: defaultValue: 'T -> keyValues: seq<string*'T> -> (string -> 'T)
Creates an optimized mapping function that maps string keys to values.
The keyValues
sequence specifies the key‐value pairs for the mapping. All keys not
specified in keyValues
are mapped to defaultValue
. A null
key is not supported.
createStaticStringMapping
throws an ArgumentException
if keyValues
contains a duplicate key or a null
key. If the generated mapping function is called with a null
string, it throws a NullReferenceException
.
The compilation strategy employed by createStaticStringMapping
does not handle all
mappings equally well. It is optimized for mapping a relatively small set of string symbols to constants. If you want to use createStaticStringMapping
to optimize a frequently used mapping in your program, you should
test how well createStaticStringMapping
handles your situation (in a Release build!)
and see whether the performance is worth the compilation costs and the additional code dependency.
Please also see the remarks at the beginning of this section.
[1] |
In the case of a reference type the values are only compared for reference‐equality. In the case of a value type the values are only compared if
the type implements System.IEquality<_> or is an int enum type.
|
---|