Closed NerdyDeedsLLC closed 3 years ago
I am aware that the plugin is simplistic in the way that it does the settings management, it just goes "what's in settings right now? store that for next time", so it does result in a lot of bloat in the settings.json
file.
Everything needs to be in the settings.json
file so that we can use the built in Settings Sync (I no longer support third-party sync extensions), so there's kind of no way around making that file larger the more you have in there.
I agree a better job could be done when it comes to shared config, whether it's theme, editor formatters, etc., but I feel like the code required to support a layering approach you describe would add complexity while only targeting a small set of users, such as yourself.
I'm unconvinced around there being performance improvements though, as the process you're describing (assuming I understood it correctly) would result in more layers of settings needing to be merged, rather than single layer which it currently is. Instead, performance gains would be better achieved by improving the extension add/remove process, as it is basic.
That said, if you're willing to provide a PR, I'm happy to review it, but I make no promises beyond that.
@aaronpowell
Hey man, that's totally fair. Indeed, it's entirely possible that I represent the extreme minority of use cases here, and this would be introducing unnecessary complexity and overhead. In fairness, I am one of those devs that is frequently brought in as a consultant to spot-problemsove, so I'm willing to admit that I have a tendency to rank edge-cases as similar in priority to happy-path cases, as usually I'm not involved for happy-path, lol. I tend to get brought in to support that happy path: to help identify when this shoulder needs to be widened, or that turn needs to be banked, or "maybe we should shore up this here bridge before we have a chasm fulla cars?"
As a consequence, I have a... call it a blind spot when it comes to prioritization of criticality (that's the PO's job, lol); I just identify where something's lacking guardrails or has the possibility of causing a pile-up and design solutions.
But, and I want to stress this, the small tome I dropped into your issue log was absolutely NOT a criticism. I was more surprised than anything, and automatic behaviors took over. Indeed, I had a strong suspicion from the get-go I was the edge case on this one and, though the impact of having a 30k config file is trivial - and it largely is; certainly is from a storage, retention, and file management standpoint; drive space is cheap, and I hemorrhage WAY more than 30k in bandwidth every time I hit a site that uses jQuery), it's also a performance hit, and a scalability risk.
Imagine if one ran, say, multiple extensions that all used the same mechanism for retention; that is, they ingested the entirety of the JSON into their own node:
activeProfileSwitcherConfig : {
{whole of the config}
}
⇓
extension2Config: {
{activeProfileSwitcherConfig},
...{whole of the config}
}
⇓
/* START NEW PROJECT */
⇓
activeProfileSwitcherConfig : {
{extension2Config},
{whole of the config}
}
⇓
extension2Config: {
{activeProfileSwitcherConfig},
...whole of the config
}
...see my concern? Toss a third into the mix and you're gonna eat up a bigger footprint than photoshop, and right quick. Worse, if one of them happens to update its snapshot automatically on file change, now you're looking at an exponential expansion instead of "only" a geometric one. If BOTH did it, well, I don't think a logarithmic expansion would take long to test the whole "drive space is cheap" bit ("but wait! There's Moore!"). I want to say I recall VSCode having a check in place to simply identify a config file that's gotten too out of hand as corrupt, dump it, and start over, but, even if I'm not misremembering there, I have no clue what that would do when given that condition combined with a third-party piece of software restoring an offsite backup every time said "refresh and renew" protocol hit.
Edge case? Even corner case? Well, yes, I suppose that'd be a fair assessment. But we're not talking about "aligning the Seven Relics of Power at the center of the Ley Line Nexus on the Day of Solstice at the precise moment of the Planetary Convergence". In this case, it's closer to, "toss your 20kg ball of uranium in the bucket with the other one(s) and lets go get lunch!" (though I admit this example does overinflate the - heh. - criticality of the issue): there's precious few scenarios out side of this flavor extension I can think of in which one would need/want/bother with the full schema. Less still the number that a user would be running concurrently. But the risk is definitely non-zero, and as I mentioned before: the (sub-?)demographic that will be drawn towards such a tool will increase it further, too.
I really do love the idea here, and I really would be happy to contribute. Your call, of course, whether you wish to merge any or all of the code; do what's best for the program. I'm really not trying to come stomping in being a rude, pedantic douche; there's no ego here, I'm just voicing a concern that only occurred to me at all because I brushed up against the edges of it.
I'll create a local branch and see if I cannot offer you more than exposition and theory. If I cannot, then thank you for taking the time to read all of this. Either way, good work on this. It's a nifty piece of code regardless.
...though, once I do fork, I intend to be be damn sure I'm not running both copies at once. Yanno... just in case, lol.
@aaronpowell
I love the idea of this. LOVE it. I've been a full-time dev for DECADES, and have RADICALLY different workflows for work vs personal, different languages, different servers/clouds, and different extensions for them all. I also write my own, a half dozen of which I have never published to the store, as they are too hyper-specific to me or my environments. Indeed, I only FOUND this extension because, fed up that starting a new project takes me 20 minutes of config, I was going to just code the damn thing myself.
But, see, here's the thing: it's safe to assume that most of the people using something like this have a great deal of configurations to handle. That's WHY they care enough to deal with it. In my case, as a for-instance, I run a BUNCH of extensions. Thing is, this tool just carbon copies the entirety of my extended profile configuration. I installed, and, not thinking twice, spun up configs for
HOME - VanillaJS (Default)
,HOME - REACT
,HOME - VUE
,HOME - VSC Extensions
,HOME - Chrome/FF Extensions
,WORK - VanillaJS (Default)
,WORK - REACT
,WORK - VUE
, andBASH - Advanced Tooling
.Then swung over to the extensions settings, thinking to fine-tailor/refine/add the always-ons, etc. "There are none? Huh. Okay. Didn't GUI 'em. S'cool." So I manually open the settings file.
...which is now over 9400 lines long.
Now, this is bad, in and of itself. Worse was when I realized SettingsSync had, with a crisp salute and a "Daaaw, you got it boss!" already overwrote my previous config with this behemoth. But the thing that really irked me? THEY'RE ALL THE SAME CONFIG. I hadn't CHANGED anything yet. I just did what I thought was the equivalent of "Save As, Save As, Save As, Save As"... except you're NOT saving the file. You're APPENDING onto the existing one.
Now, I get that: SettingsSync won't do you much good for loose, external files. That's fair. But, as another for-instance, here, yanno what I almost NEVER change? My editor font. Or my preferred quote style. Or whether or not I want the IDE to auto-close (ANYTHING). Or the SETTINGS for most of the 180 extensions I run SOMETIMES, situation-specific, some of which are 200+ lines of configuration. Each.
So what if... and I'm just spitballing here... You have a DEFAULT CONFIG, containing ALL of the IDE settings, ALL of the extension data (and with all of them set to DISABLED, so the IDE loads FAST and the ExtensionHostManager ONLY needs to worry about the couple exceptions: "initialization AlwaysOn's" and ProfileSwitcher).
Then, when I create a profile, it takes a similar snapshot, and recursively DIFFS the two JSON objects. The DIFFERENCES get stored, NOT the whole config (e.g. if I have an object with all the alphabet as keys, and a letter-appropriate animal as values -
{"a":"alligator", "b":"babboon", "c":"cheetah" ...}
- I only worry about storing the data when you change{"s":"sloth"}
to{"s":"sabretooth tiger"}
, and even then, I ONLY store the ONE key/value pair).OnLoad, VSC ingests the default config. Your extension finishes initialization, and begins to load the desired profile. This is accomplished by
nativeProf
switcherProf
nativeProf
JSON object, and deep-copying it, replicating all of the information contained within EXCEPT extension data into a new object, call itconstructedProfile
(let constructedProfile = Object.assign({}, nativeProf); constructedProfile.extensions = [];
).constructedProfile = Object.assign(constructedProfile, switcherProf);
constructedProfile.extensions = Object.entries(extensions).map(ext=>Object.assign({}, nativeProf.extensions[ext[0]], alwaysOnExtensions.extensions[ext[0]], ext[1])
.constructedProfile
as the active profile. Bam. Done.The net result here is you wind with with the following structure:
... which, while it does result in a substantive increase in the size of
vanillaConfig
, it'll very likely be less than double, and I GUARANTEE less than the octuple I'm looking at now. Additionally, it'll leverage all the activation and usage code you have now. Finally, SettingsSync will store both all the saved profiles, the default profile, and the most recently active profile, too.LIkewise, this set of changes both obviates the issue of "how do I make changes to SEVERAL profiles if I decide I really need to use this new set of snippets EVERYWHERE I use JS code?" and opens you up for the ability to present what would be a fabulously-useful dialog announcing...
...and followed by a...
If you're open to contributions, I'll fork the code, implement, and open a PR myself. I'm not just wandering in here to tell you how to do your job; I'll happily double down and help out. I'm not kidding when I say I both love the idea and had been gearing up to just make it myself. I have a similar tool for Chrome (where I have some 450 extensions installed, though generally only USE 4-8 at a time). Big shock, though: the tools that exist for such management are either woefully-underpowered, excruciatingly-slow, or hinky as all get out - written in Chinese and asking for a credit card number as a CAPTCHA solution ("Prove you're a human! Buy me something nice!").