-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Refactor migrations to only marshall yaml twice #4318
Refactor migrations to only marshall yaml twice #4318
Conversation
Created as draft because I have some inline docs changes I want to make, but this is the meat and potatoes. |
26434f9
to
61756b7
Compare
Okay, cleaned those things up, ready for review! |
21ms on each startup is indeed something, albeit a small improvement. But the complexity cost is high and there's a lot more chance of errors now that various places need to report on whether a change occurred, and any one of those might report incorrectly. What's it like if we just do a deep comparison at the end before marshalling back? I suspect that would give us roughly the same speed up, without the extra complexity. |
10ae48f
to
8e93a68
Compare
Pushed a new version that does the unmarshalling twice. That's the only way I know to do a deep copy! Alternatively happily welcome. My computer was seemingly feeling snappier today, so the test results were as follows: Existing code
Previous Implementation
New implementation
I'm still happy with new implementation though, since it'll make future migrations cost basically nothing. |
8e93a68
to
fbfadbe
Compare
fbfadbe
to
264b998
Compare
Might be worth looking into https://github.com/brunoga/deep instead? I have no experience with it myself, just found it with a cursory google search. |
Something that just occurred to me: what if we just had some check at the start to see if the current yaml satisfies the schema? if so, we don't need to do any migrating. Then it won't matter how long it takes to do the migration because it will only need to run occasionally (after a user updates lazygit) |
264b998
to
532de87
Compare
@jesseduffield That worked quite smoothly! I spun it off into its own PR, because it ends up being a totally separate section of code: #4334 I've removed the benchmark commit from this branch, since it is no longer a relevant thing to be tracking. I still think this refactor stands on its own merits. It feels more elegant for me for the individual migrations to be expressed in terms of acting on the root |
I'm against this approach, because I'm not sure we can really trust the schema validation enough for this. Here's one example: the schema declares the context of a custom command as a string, because we can't do any better; conceptually it's a bunch of enums separated by commas. Now suppose we decide to rename one of the enum entries (e.g. we find a better name for "commitFiles"). So we write a migrator that splits the context by comma, and renames every occurrence of "commitFiles" to that better name. Schema validation doesn't catch this, because it's still a string before and after. Maybe this is a contrived example, but it does illustrate the problem. I'd much rather we use the actual migrations that we perform to tell us whether anything happened. I still find the deepCopy/deepEquals approach the most promising. |
@ChrisMcD1 I'm confused, can you explain more what you're doing in that PR? It doesn't seem to have anything to do with Jesse's suggestion as far as I can see. |
Good points @stefanhaller |
Oh and btw, I wouldn't be surprised if doing a schema validation is actually more expensive than running the migrators and seeing if they changed something. That's just a guess though, would have to be measured of course. |
I'm now realizing the idea of #4334 doesn't really work in the general case, as you point out with the string example. And also doesn't even work in many normal cases. The case where it did work, and the one I manually tested it on was:
In my head, Closing that PR, cause it makes no sense! |
532de87
to
f2bb202
Compare
Added back the benchmark, since this is now in the normal startup path. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, pending one comment
pkg/config/app_config.go
Outdated
if !reflect.DeepEqual(rootNode, originalCopy) { | ||
newContent, err := yaml_utils.YamlMarshal(&rootNode) | ||
if err != nil { | ||
return nil, fmt.Errorf("Failed to remarsall!") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return nil, fmt.Errorf("Failed to remarsall!") | |
return nil, fmt.Errorf("Failed to remarshal!") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, and added a %w
for the error as well
f2bb202
to
d39f883
Compare
Ok, looks good to me too. Nice improvement. I'd still find it interesting to play with using a deep copy instead of unmarshalling twice, but we can do that later if we find it important enough. Merging for now. |
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [jesseduffield/lazygit](https://github.com/jesseduffield/lazygit) | minor | `v0.47.2` -> `v0.48.0` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>jesseduffield/lazygit (jesseduffield/lazygit)</summary> ### [`v0.48.0`](https://github.com/jesseduffield/lazygit/releases/tag/v0.48.0) [Compare Source](jesseduffield/lazygit@v0.47.2...v0.48.0) <!-- Release notes generated using configuration in .github/release.yml at v0.48.0 --> #### What's Changed ##### Enhancements 🔥 - Custom commands submenus by [@​stefanhaller](https://github.com/stefanhaller) in jesseduffield/lazygit#4324 ##### Maintenance ⚙️ - Refactor migrations to only marshall yaml twice by [@​ChrisMcD1](https://github.com/ChrisMcD1) in jesseduffield/lazygit#4318 **Full Changelog**: jesseduffield/lazygit@v0.47.2...v0.48.0 </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xODIuNCIsInVwZGF0ZWRJblZlciI6IjM5LjE4Mi40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiXX0=-->
In the solving of #4194 we had some discussion about the repeated marshalling and unmarshalling of the content in our migrations. #4194 (comment).
I was feeling the itch to see if there was a meaningful performance impact to that, and this is the results! I added a benchmark first that uses the entirety of
Config.md
. This ensures a worst-case scenario for the repeated parsing, and probably at least 1 user has done this for their config. Here were the benchmark results prior and after this PR:Before
so somewhere in the range of 14 to 21 ms added to startup time.
After
So somewhere between 2.6 and 3.1 ms.
Is that a meaningful speedup? I'm not sure, but it's something! I had to add the bit of complexity mentioned in the comment to track whether we had made any changes, but that doesn't feel fundamentally much more complex to me, since we were already implicitly tracking that fact with whether the string file changed.
go generate ./...
)