What is Monomorphization?

I was reading this post and came across this term monomorphization

I would like to know:

  • What is its meaning?
  • when does this process occur?
  • What performance gain/loss is achieved by this process?
Author: Matheus Catarino França, 2020-06-22

1 answers

Sometimes we write polymorphic codes. One of the most used polymorphisms is virtualization where the Pointer will decide at runtime what to do in a specialized way, but the code written is generic, you say you need to do an operation that a base object is capable of, but objects derived from it also know how to do and can do in a more specific way. I won't talk too much about it, see another answer if you don't master the subject.

But there is another very interesting polymorphism that is parametric. some pretty powerful like C++, others less like Java or C # which are generics. I suggest reading more in parametric Polymorphism and overhead in Java and C++.

They can be used in various ways, among them exactly what is said above. You write a generic code, a feedback for the actual code, and on execution the actual code specific to the situation will be executed. The difference in decision whether to run a base or derivative method is that this mechanism allows the choice to be made at compile time.

If this is done, monomorphization is performed. Note that some mechanisms, especially of generics , do not do this whenever you have a type parameterization and the decision of what to use can be made at runtime, so the code remains polymorphic in the executable.

Monomorphization is to take that polymorphic written code and turn it into a monomorphic code, so a code could have multiple shapes and goes on to have a specialized shape for each situation used.

For example, if the code of a class is polymorphic and it accepts anything that is comparable (it has ability to compare between objects), so what is going to use ali just needs to call a comparison, the object needs to be able to do that. And let's say you called that which is polymorphic in three situations, with a int, with a String and with a Date. The compiler will create three methods equal to the one written, each of these methods will use one of these types to make the comparison.

This is quite interesting because it does not have virtualization, does not have to decide at runtime what to do, gets faster and can even allow certain optimizations.

But it's not always good. Let's say you used this polymorphic method in 200 different types. 200 methods will be generated different.

I will compare with a code that everyone understands easy:

for (int i = 0; i < 2; i++) print(i);

Is the same as:

print(0)
print(1)

In fact a compiler that does optimizations will probably turn the former into the latter and be faster.

But what if the code is:

for (int i = 0; i < 200; i++) print(i);

Pays to do the same?

And if so:

for (int i = 0; i < user_entry; i++) print(i);

Understood that you have a variable that is only known at runtime, right? You can optimize, even if the value is 0, 1, 2 or other low?

What is its meaning?

The act of transforming a polymorphic generic code into a monomorphic code.

When does this process occur?

In C++, during compilation always.

What performance gain/loss is achieved by this process?

The of not needing the indirection to access a method and possible optimizations because of this. Loses staying with a large executable Nothing much.

Real example:

template <class T>
    T max(T a, T b) { return (a > b ? a : b); }

When to call like this:

max(1, 2)

The compiler will generate a method like this:

int max(int a, int b) { return (a > b ? a : b); }

And for each type that is consumed it will generate such a method. That template Method, which is polymorphic by definition, will never exist, it's just a template for creating the actual methods that are monomorphic.

Note that this type of code is old for C++ and would give error on objects that cannot make a comparison, today it would normally use a concept to restrict what type can be used there and get more robust, but that's another matter.

Without monomorphization would have to do something like this:

void *max(void *a, void *b) { return (*a > *b ? *a : *b); }

And then the use:

*(max(&1, &2))
 3
Author: Maniero, 2020-06-23 12:51:31