Skip to main content

Infer.NET development

Estimating computational cost

This page describes the design of a compiler transform for estimating the computational cost of the code passed into the transform, in the form of an expression for the time and memory used.

In the following, x is of type T, y is an array with element type T and i and j are indices in loops of size I and J. This table doesn’t take into account conditional execution (if statements) or sparse arrays.

Element Code Execution time Memory (heap) Notes
Method call x = ​MyMethod(a,b,c) timeof(MyMethod()) sizeof(T) if T is a class or 0 otherwise  
  x = ​MyMethod(a,b,c, x) where x is ‘result’ parameter timeof(MyMethod()) 0  
  y[i,j] = ​​​MyMethod(a,b,c) in loops of size I,J ​I.J.timeof(MyMethod()) I.J.​sizeof(T)  
  var x = ​​​MyMethod(a,b,c) in loops of size I,J ​​I.J.timeof(MyMethod()) sizeof(T) if T is a class or 0 otherwise ​The effect of churn is ignored.
Object creation x = T() timeof(T()) ​sizeof(T) if T is a class or 0 otherwise  
  var x = T() in loops of size I,J I.J.timeof(T()) sizeof(T) The effect of churn is ignored.
Array creation ​var y = new T[I,J] I.J.timeof(T()) if T is a struct or 0 otherwise I.J.​sizeof(T) if T is a struct I.J.sizeof(ref) if T is a class. sizeof(ref) represents the size of a reference.
  var y = new T[J] in loop of size I I.J.timeof(T()) if T is a struct or 0 otherwise J.sizeof(T) if T is a struct J.sizeof(ref) if T is a class  
  y[i] = new T[J] in loop of size I I.J.timeof(T()) if T is a struct or 0 otherwise I.J.sizeof(T) if T is a struct I.J.sizeof(ref) if T is a class  

The expressions for time and memory would be stored in a Cost object attached as an attribute on the expression and/or containing statements. The Cost object would:

In addition, there would be an aggregator that would collect all costs for an entire method or program and highlight bottleneck expressions e.g. the top N expressions in terms of cost or memory.

Design questions: