aristanetworks / purescript-backend-optimizer

Optimizing backend toolkit and modern ECMAScript backend for PureScript
MIT License
201 stars 18 forks source link

Inline method calls via a directive #54

Closed gbagan closed 1 year ago

gbagan commented 1 year ago

Hi,

First of all, thank you for this great work on purescript-backed-optimizer.

I thought about this proposal but I'm not very familiar with purescript-backend-es so it might be a bad idea.

My problematic is that purescript-backend-es can inline Purescript functions but cannot inline FFI functions (written in JS). But, very often (in my experience), a FFI function in Purescript is just a call of a method in JS For example:

foreign import someFuncImpl :: EffectFn4 ObjType Val1Type Val2Type Val3Type RetType
export function someFuncImpl(obj, val1, val2, val2) {
  return obj.someMethod(val1, val2, val3)
}

Would it be possible to inline this function by adding a (new) directive like

-- @inlineMethod Example.someFuncImpl "someMethod" arity=3
natefaubion commented 1 year ago

My assumption is that functions such as this are very likely going to be inlined by any JIT anyway. There isn't an advantage here as far as opening up other optimizations on the backend-optimizer side. The advantage may be slightly reduced bundle size, but that may not even be the case with minification (since the method name is unlikely to be shortened).

Do you have any data to suggest that this is an advantageous thing to do? Ideally, if this were a significant optimization opportunity, I think it would be the most convenient to parse the FFI file rather than essentially duplicating the definition in a directive.

gbagan commented 1 year ago

Yes, you are right. I've done benchmarks on JS maps with the method set and get and functions (uncurried and curried) that call them. The uncurried functions have exactly the same performance as direct method calls. However, the curried functions are slightly slower (30% slower).

So, sorry for this bad idea.

natefaubion commented 1 year ago

I don't know if it's a bad idea, per se. I would say it's definitely in the realm of an aesthetic optimization. Sometimes it's nice to see the "real" code we want rather than the indirection. I'd say I'm opposed to this as a directive, as it essentially becomes an arbitrary rewrite regardless of what's in the FFI (that sounds like a source of bugs to me), but if it could be automated such that the actual FFI file is the source of truth, it's relatively harmless. Unfortunately, it would require some level of parsing, and I really (really^really) don't want to FFI to NPM libraries for that.