Closed MrMage closed 4 years ago
Update: https://github.com/apple/swift-nio/pull/943 should significantly alleviate these issues once this project moves to NIO 2.
This will be improved upon by https://github.com/vapor/core/pull/203#issuecomment-482040419. The remaining runtime might be more due to other factors, e.g. date formatting and String.htmlEscaped()
being slow.
In any case, I think that rendering 500 table rows of a semi-complex model (see https://github.com/vapor/leaf/blob/e06abf2e5cff23e5e8c8fa096718258ee27f4846/Tests/LeafTests/LeafTests.swift#L556) should take less than 500 milliseconds.
Closing as template kit is not used with Vapor 4 and new behaviour is in LeafKit - if this is still an issue please create an issue on that repo. Thanks!
After the optimizations proposed in https://github.com/vapor/template-kit/pull/50/files, a significant portion of the time needed to encode/render templates is spent calling NIO operations on already-fulfilled futures (see https://github.com/vapor/leaf/pull/137 for the corresponding benchmark):
https://github.com/vapor/core/pull/199 has alleviated this problem, but it is still significant. Essentially, the current render process consists of linking thousands of small futures — at least one for each variable printed in the template. Almost all of these futures are already fulfilled when they are created, because none of TemplateKit's/Leaf's default tags perform any non-blocking operations.
One option to alleviate this could be to make the rendering process itself blocking. I understand that the option to have non-blocking ("future") passes in the encode/render steps is a great option, but it does not seem to be used in practice right now. In addition, users could still manually "prepare" the "future" parts of their templates before calling a "blocking" render pass that simply processes the already-prepared template data in one fell swoop.
Another alternative would be to introduce a
FutureOrFulfilled<T>
type, which could use shortcuts when it has already been fulfilled at creation time (e.g. not submitting blocks to the run loop). However, that would still retain some overhead and make the implementation more complicated.I'm not sure if the approach suggested above would be the right way forward, but it feels like template rendering in particular creates so many already-fulfilled futures that the overall render time is impacted significantly.