Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade HtmlFlow to release 3.5 #56

Merged
merged 1 commit into from
Jan 13, 2020
Merged

Upgrade HtmlFlow to release 3.5 #56

merged 1 commit into from
Jan 13, 2020

Conversation

fmcarvalho
Copy link
Contributor

  • Fixed a problem where the block html was written two times into the response. Reported by @Vest at Add HtmlFlow #34 (comment)
  • Updated the HtmlFlowIndexView according to the new behavior of HtmlFlow in version 3.3. (https://github.com/xmlet/HtmlFlow#33-august-2019) where it: ”disallows the use of chained calls to dynamic() due to unexpected cache behaviors.”. Thus we had to replace the inner invocations of dynamic() by of().
  • Changed the static method getView() of HtmlFlowIndexView with a static field view.
  • Added the threadSafe() initialization to the previous view to enable safe use on concurrent benchmarks.

* Fixed a problem where the block html was written two times into the response. Reported by @Vest at jreijn#34 (comment)
* Updated the HtmlFlowIndexView according to the new behavior of HtmlFlow in version 3.3. (https://github.com/xmlet/HtmlFlow#33-august-2019) where it:”disallows the use of chained calls to dynamic() due to unexpected cache behaviors.”. Thus we had to replace the inner invocations of dynamic() by of().
* Changed the static method getView() of HtmlFlowIndexView with a static field view.
* Added the threadSafe() initialization to the previous view to enable safe use on concurrent benchmarks.
Copy link
Owner

@jreijn jreijn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great @fmcarvalho . Thanks for contributing.

@jreijn jreijn merged commit 80c37b0 into jreijn:master Jan 13, 2020
@Vest
Copy link
Collaborator

Vest commented Jan 14, 2020

@fmcarvalho I didn't have time to review your new PR. I found out that you replaced the public function getView with the static variable view. So it means that comparing to other engines, that we were using in this repository, your view is not recreated on every test iteration.

I debugged your code for quite a long time and I found out that with this change, the shared DynamicHtml object uses HtmlVisitorCache, where the property isCached is equal to true for every thread that is created by Spring.

E.g. if you put the breakpoint here:

// HtmlFlowView.renderMergedTemplateModel
String html = HtmlFlowIndexView.view.render(model);

and step into

// DynamicHtml.render
public final String render(T model) {
    binder.accept(this, model);
    return getVisitor().finished(); // <-- here
}

you will find that the method finished reads cached parts of the dynamic content from cacheBlockList. See the image below:

Debug of cacheBlockList behavior

Maybe I am wrong, but I guess that what happens is unfair to other engines, where the view is built and parsed at runtime for each request individually. In your case, we just take strings from the cache.

I will return my change back, but leave your PR with the new version of HtmlFlow.

@jreijn if you are interested in this finding, you can test the PR as well.

@fmcarvalho
Copy link
Contributor Author

fmcarvalho commented Jan 14, 2020

@Vest You are not right when you said: "the method finished reads cached parts of the dynamic content from cacheBlockList.". It only reads the static parts and not the dynamic parts.

As you can see in your print screen you only have 2 blocks in cacheBlockList the prologue that begins with <DOCTYPE html>\n<html>... and the epilogue with \n\t\t</div>\n\t\t\<script... all the rest in the middle is dynamically generated has expressed through the call to dynamic() here and it is not in cache.

You can observe it by passing different models to this view and you will see different outputs.

The same approach happens with textual templates engines. The static parts are only concatenated with the dynamic parts. For example in JSP we do: "<%@ include file="head.jspf" %>" where head.jspf has an equivalent HTML definition to that one preceding the call to dynamic() in HtmlFlowIndexView.

Yet, in HtmlFlow since the static parts are defined through functions, we must first invoke those functions to get the output of the static part, that is in turn stored in the cacheBlockList.

Maybe the name cacheBlockList generates some confusing here and should be better called staticBlockParts or something like that.

@Vest
Copy link
Collaborator

Vest commented Jan 14, 2020

yes, it seems that I was wrong. I apologize. This name was really confusing, because I was trying to understand what kind of data is cached and why by the time when the rendering starts, the string builder is initialized with the data.

Ok, it seems fine, or at least I didn't find anything suspicious.

Thanks

@fmcarvalho
Copy link
Contributor Author

fmcarvalho commented Jan 14, 2020

@Vest We are already using the term static in some code of this class such as staticBlockIndex. Although the HtmlVisitorCache is public it plays an internal role inside HtmlFlow and I will rename it and all its related members from cache to something that suppresses that ambiguity and misleadings. Names should clear express their semantics and here we are creating unnecessary confusing.

BTW when I am running the benchmarks I am getting slightly different results from those ones published in benchmarks-102019. I know those results depend of many different environment characteristics and hardware. But, I cannot observer JSP and Freemaker being the top two most performant. And I cannot observe either the JSP gaining for almost 3 or 4 seconds above competence.

@Vest
Copy link
Collaborator

Vest commented Jan 14, 2020

I can repeat the tests tomorrow just for your curiosity, but indeed these results are not 100% precise. Sometimes they are 73% reproducible :)
It is difficult to sort them by time and choose the fastest. Second more or less and you get a different picture.

@fmcarvalho
Copy link
Contributor Author

@Vest did you have the opportunity to run the tests again? Did you see differences in results?

btw I forgot to update the htmlflow version in README.md to 3.5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants