Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tupled Type Test Pattern Matching caused exponential IL growth #5212

Closed
manofstick opened this issue Jun 19, 2018 · 3 comments
Closed

Tupled Type Test Pattern Matching caused exponential IL growth #5212

manofstick opened this issue Jun 19, 2018 · 3 comments

Comments

@manofstick
Copy link
Contributor

The following functions demonstrate the affect:

let f (a:obj) (b:obj) =
    match a, b with
    | :? char, :? char -> 0
    | :? int,  :? int  -> 1
    | _ -> -1

let g (a:obj) (b:obj) =
    match a, b with
    | :? char, :? char -> 0
    | :? int,  :? int  -> 1
    | :? byte, :? byte -> 2
    | _ -> -1

let h (a:obj) (b:obj) =
    match a, b with
    | :? char,  :? char  -> 0
    | :? int,   :? int   -> 1
    | :? byte,  :? byte  -> 2
    | :? float, :? float -> 3
    | _ -> -1

So type size of the Il generated from those functions is 60, 143, 337 bytes respectively.

The array checking code in prim_types.fs in the funciton GenericEqualityObj which has 8 type-checks creates IL which is around 8K.

Expected behavior

This should be a linear increase.

Actual behavior

The exponential behaviour is due to the AST duplicating the remaining code in both the first and second failing check.

Known workarounds

You can work around this by putting a catch all, and then matching again.

In the prim_types code this would look like this:

match arr1,yobj with 
| (:? (obj[]) as arr1),    (:? (obj[]) as arr2)      -> GenericEqualityObjArray er iec arr1 arr2
| _ ->
match arr1,yobj with 
| (:? (byte[]) as arr1),    (:? (byte[]) as arr2)     -> GenericEqualityByteArray arr1 arr2
| _ ->
match arr1,yobj with 
| (:? (int32[]) as arr1),   (:? (int32[]) as arr2)   -> GenericEqualityInt32Array arr1 arr2
| _ ->
match arr1,yobj with 
| (:? (int64[]) as arr1),   (:? (int64[]) as arr2)   -> GenericEqualityInt64Array arr1 arr2
| _ ->
match arr1,yobj with 
| (:? (char[]) as arr1),    (:? (char[]) as arr2)     -> GenericEqualityCharArray arr1 arr2
| _ ->
match arr1,yobj with 
| (:? (float32[]) as arr1), (:? (float32[]) as arr2) -> GenericEqualitySingleArray er arr1 arr2
| _ ->
match arr1,yobj with 
| (:? (float[]) as arr1),   (:? (float[]) as arr2)     -> GenericEqualityDoubleArray er arr1 arr2
| _ ->
match arr1,yobj with 
| _                   ,    (:? System.Array as arr2) -> GenericEqualityArbArray er iec arr1 arr2
| _ -> xobj.Equals(yobj)
@dsyme
Copy link
Contributor

dsyme commented Jun 19, 2018

@manofstick Thanks, good report.

@abelbraaksma
Copy link
Contributor

abelbraaksma commented Jun 19, 2018

This is similar, and essentially the same as what happens with the IL in #4691, I think. FWIW, this behavior can also be seen with nested/tupled DUs, not just type test patterns.

manofstick added a commit to manofstick/visualfsharp that referenced this issue Jun 25, 2018
manofstick added a commit to manofstick/visualfsharp that referenced this issue Aug 7, 2018
manofstick added a commit to manofstick/visualfsharp that referenced this issue Aug 7, 2018
manofstick added a commit to manofstick/visualfsharp that referenced this issue Aug 7, 2018
manofstick added a commit to manofstick/visualfsharp that referenced this issue Aug 8, 2018
manofstick added a commit to manofstick/visualfsharp that referenced this issue Aug 12, 2018
@cartermp cartermp added this to the Unknown milestone Aug 25, 2018
@dsyme
Copy link
Contributor

dsyme commented Mar 31, 2022

This was fixed by recent improvements to pattern compilation

@dsyme dsyme closed this as completed Mar 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants