Skip to content

Conversation

billglover
Copy link
Contributor

This PR fixes #3116. I have added test cases to existing tests. I've made the assumption that escaping the closing brace is optional (i.e. I'm not checking that an escaped opening brace is matched with an escaped closing brace). See test cases for specific examples.

@CLAassistant
Copy link

CLAassistant commented Mar 6, 2020

CLA assistant check
All committers have signed the CLA.

@billglover billglover changed the title Rework Replacer loop to ignore escaped braces v2: Rework Replacer loop to ignore escaped braces Mar 6, 2020
Copy link
Member

@mholt mholt left a comment

Choose a reason for hiding this comment

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

Thanks for the PR!

This looks good, I like how simple it is. But one question I am wondering about that I think is kind of important at this stage, is how does this affect Replacer performance?

I learned that strings.Replace* is very inefficient: #2674

Would you mind writing a simple Benchmark...() test function and run it before and after these changes just to verify that it doesn't slow down placeholder performance? Thanks!

@mholt mholt added the v2 label Mar 6, 2020
@mholt mholt added this to the v2.0.0-beta.16 milestone Mar 6, 2020
@billglover
Copy link
Contributor Author

No problem. I'll add a couple of benchmarks and share the results.

@billglover
Copy link
Contributor Author

Benchmark before this change:

BenchmarkReplacer-8   	18244922	        61.0 ns/op	      48 B/op	       1 allocs/op

Benchmark after this change:

BenchmarkReplacer-8   	 3793706	       310 ns/op	     176 B/op	       5 allocs/op

Good catch, you are correct. I'll have a think about how to do this more efficiently. It is almost certainly possible to do this during the main for loop as part of the replace function.

@mholt
Copy link
Member

mholt commented Mar 6, 2020

Awesome, thanks. Yeah, I wonder if it's possible to just skip the escaping backslash when building the string...

Edit: PS. If you want to add your benchmark to the test file that'd be cool too! For any future changes.

@billglover
Copy link
Contributor Author

Benchmark after optimisation:

BenchmarkReplacer-8   	10560511	       107 ns/op	      48 B/op	       1 allocs/op

Same number of allocs and bytes per operation. Still a little slower though. I'd be very interested in feedback on clarity.

@mholt
Copy link
Member

mholt commented Mar 6, 2020

Still a little slower though.

I hypothesize that it's only slower on the case of JSON input (i.e. input where escapes actually happen). You can vary your input string on the benchmark test and see if that's true.

Still, allocations are the big deal -- which is fixed now -- and the speed decrease is minimal. If that speed decrease is in fact just for escaped inputs, then that's probably totally acceptable.

I have a comment/question I'll inline.

Thanks for working on this!

Copy link
Member

@mholt mholt left a comment

Choose a reason for hiding this comment

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

Thanks for working on this! Left a few more comments.

@mholt
Copy link
Member

mholt commented Mar 6, 2020

Oh, and just before we merge, could you post the final benchmarks? Thanks again!

@billglover
Copy link
Contributor Author

Benchmarks for three different scenarios:

  • no_placeholder - simple string
  • placeholder - {"json": "object"}
  • escaped_placeholder - \{"json": \{"nested": "{bar}"\}\}
BenchmarkReplacer/no_placeholder-8         	100000000	        11.4 ns/op	       0 B/op	       0 allocs/op
BenchmarkReplacer/placeholder-8            	21644844	        53.0 ns/op	      32 B/op	       1 allocs/op
BenchmarkReplacer/escaped_placeholder-8    	10888167	       108 ns/op	      48 B/op	       1 allocs/op

@mholt
Copy link
Member

mholt commented Mar 6, 2020

Performance-wise, it's looking good. If we keep it in this range for any remaining, last-minute changes, LGTM!

This commit removes the additional check for input in which the closing
brace appears before the opening brace. This check has been removed for
performance reasons as it is deemed an unlikely edge case.
@billglover
Copy link
Contributor Author

Benchmarks for: e385e0d

BenchmarkReplacer/no_placeholder-8         	160360214	         7.38 ns/op	       0 B/op	       0 allocs/op
BenchmarkReplacer/placeholder-8            	21445204	        54.8 ns/op	      32 B/op	       1 allocs/op
BenchmarkReplacer/escaped_placeholder-8    	 9841627	       122 ns/op	      48 B/op	       1 allocs/op

@billglover
Copy link
Contributor Author

Benchmarks for: 681531b

BenchmarkReplacer/no_placeholder-8         	158008672	         7.57 ns/op	       0 B/op	       0 allocs/op
BenchmarkReplacer/placeholder-8            	22138293	        53.8 ns/op	      32 B/op	       1 allocs/op
BenchmarkReplacer/escaped_placeholder-8    	10015346	       122 ns/op	      48 B/op	       1 allocs/op

Copy link
Member

@mholt mholt left a comment

Choose a reason for hiding this comment

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

Nice work!! This is a great solution IMO. Simple, elegant, and does the job without any measurable performance hit.

Thanks for your contribution! Please feel free to participate again, would be happy to work with you any time. If you're interested, I can send you an invite to our dev Slack (just let me know the email).

@mholt mholt merged commit 36a6c7d into caddyserver:v2 Mar 8, 2020
@billglover
Copy link
Contributor Author

Many thanks for all the support and patience as I worked through this. I'm in the process of deploying Caddy for a small site at the moment. This should give me a little more experience using the application. As I do, I'll take a look at the open issues and see if anything stands out.

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.

3 participants