I'm reading about strict data constructors. The linked Wiki article states that,
"strictness annotations can make performance worse [because] a strictness annotation forces the compiler to ensure that the field is fully evaluated before building the constructor, and if it turns out that the field was already evaluated then this is just wasted work".
I do not understand why if the field was already evaluated it is wasted work, since its value is needed anyway to apply the constructor.
Is there an example that illustrates this problem or other loses of efficiency due to strictness?
Forcing a value, even if it is already evaluated, has a small but existent cost.
If you have a pointer to something that might or might not be already evaluated (a thunk or a value), and you wrap it in a lazy data constructor, you just copy that address to its place in memory. That’s quick.
If you have such a pointer and you want to store it in a strict constructor, you have to evaluate it first. This requires checking the lowest bits of the pointer for possible tags (a trick to indicate evaluatedness). If no tag is present, you actually jump to this pointer to enter the thunk. Before you do that, you have to push an return frame onto the stack so that execution flow returns to you in the end. Then the thunk evaluates itself, puts the result in a register and jumps to the return address. Then you can put this result into memory.
So even if the thing you point to is already evaluated, you still have to do the tag check. And I believe in some cases evaluated things do not have a tag (it is optional), so all the other work might still happen – for nothing.