8000 Reduce number of content sequences to speed up compile time by grego · Pull Request #33 · maciejhirsz/ramhorns · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Reduce number of content sequences to speed up compile time #33

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

Merged
merged 1 commit into from
May 28, 2020

Conversation

grego
Copy link
Contributor
@grego grego commented May 17, 2020

Consider the test example:

    #[derive(Content)]
    struct A {
        ain: u8,
    };
    #[derive(Content)]
    struct B {
        bin1: f64,
        bin2: f64,
    };
    #[derive(Content)]
    struct C(&'static str);
    #[derive(Content)]
    struct D(bool);

    #[derive(Content)]
    struct Page {
        a: A,
        b: B,
        c: C,
        d: D,
        other: &'static [Page],
    }

In order for it to compile, the recursion limit needs to be raised to 369 and then, it takes roughly 25s to compile on my machine. That's because the compiler needs to "prepare" for every possible sequence of contents. However, most of them are very unlikely to occur.

This PR reduces these by "crawling back" in the content tree when the section is not found in the current content. Effectively, the current content is forgotten and not used in the further content sequences. In other words, the sections in the content sequence always lie on a path in the content tree. All of the previous contents are the ancestors of the current one. This decreases the number of possible content sequences from quartic (the length of the content sequence is 4) to linear, eradicates the need to raise the recursion limit and the compilation is significantly faster: roughly 2.5s on my machine.

The mustache specification does not mention using sections from the parent contexts at all, so this is kind of an extra feature anyway. All tests are passed and in the majority of cases, the behaviour remains the same. Then, there are some edge differences. Consider the structs from the example.

{{#a}} {{#b}} {{bin1}} + {{ain}} + {{bin2}} {{/b}} {{/a}}
now doesn't render {{ain}}, as it's not found in b, nor in any of the parent contents in the content tree. We can always return to the previous behaviour by using
{{#a}} {{#b}} {{bin1}} + {{#a}} {{ain}} {{/a}} + {{bin2}} {{/b}} {{/a}}.
This is quite verbose, on the other hand it makes clear in which content the variable is expected.
However, mostly a much simpler solution would suffice:
{{#a}} {{#b}} {{bin1}} {{/b}} + {{ain}} + {{#b}} {{bin2}} {{/b}} {{/a}},
or even
{{#b}} {{bin1}} + {{#a}} {{ain}} {{/a}} + {{bin2}} {{/b}}.

The only case where a workaround of this sort is not possible is when a and b are both lists, but my imagination is not sufficient to conceive an actual example of where a construct like that would be desired. I don't think it's required by the specification, as the sections form parent contexts are not mentioned there, and speeding the compilation up, as well as reducing the binary size provides more practical advantages.

#[inline]
fn render_field_escaped<E: Encoder>(
&self,
_hash: u64,
_name: &str,
_encoder: &mut E,
) -> Result<bool, E::Error> {
Ok(false)
) -> Result<(), E::Error> {
Copy link
Owner

Choose a reason for hiding this comment

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

Sorry for reviewing so late. I'm using the return values in the #[ramhorns(flatten)] IIRC, so I'm not sure if this breaks things. I'm actually surprised CI passed here.

Copy link
Contributor Author
@grego grego May 26, 2020

Choose a reason for hiding this comment

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

As far as I see, only the return values of the Content trait (not ContentSequence trait) are used in the flatten implementation, and those remain unchanged. I can bring ContentSequence return types back if a future use is planned, though.
I just changed the return types because these values were not used anywhere at the moment.
Edit: clarify.

Copy link
Owner

Choose a reason for hiding this comment

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

Ah, that makes more sense, I should have read more carefully!

@maciejhirsz maciejhirsz merged commit 34f426b into maciejhirsz:master May 28, 2020
@grego grego deleted the compile_speedup branch June 6, 2020 08:59
@grego
Copy link
Contributor Author
grego commented Jun 6, 2020

Please, could you submit a new release with this PR merged?

@maciejhirsz
Copy link
Owner

Published now.

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.

2 participants
0