I created a test page where I'm using hyperHTML to showcase 10,000 buttons. The code is a little large to post onto stackoverflow, but you can view source on this page here to see the code (expect delay after clicking).
hyperHTML is taking more time than expected to complete its work, which makes me think I'm misusing it.
Any suggested optimizations?
Update: It seems I was using an older version of hyperHTML. The current version is blazing fast on this test.
Update beside the test being not a real world use case, there was room for improvements on linearly holed template literals so that 7 seconds now are down to roughly 70 ms ... however, the rest applies, that is not how you use hyperHTML.
I created a test page where I'm using hyperHTML to showcase 10,000 buttons
You are not using hyperHTML properly at all. It's a declarative library that wants you to forget the usage of document.createElement or addEventListener or even setAttribute.
It looks like you are really trying hard to avoid all its utility with this example, and since this is not your first question about hyperHTML, it looks like you are avoiding its documentation and examples on purpose.
In such case, what are you trying to achieve?
The code is a little large to post onto stackoverflow
That code is an absolute nonsense, IMO. No sane person would ever write 10000 buttons inline like you did there, and I bet that was machine generated indeed.
The code to create 10K buttons, or one of the ways, in hyperHTML, fits very easily in this forum:
function createButton(content) {
return wire(document, ':' + content)`
<button onclick=${onclick}>${content}</button>`;
}
function onclick(e) {
alert(`You clicked a button labeled: ${e.target.textContent}.`);
}
const buttons = [];
for (let i = 0; i < 10000; i++)
buttons.push(createButton('btn-' + i));
bind(document.body)`${buttons}`;
That's it. You can eventually optimize the container that will render such content, and to preserve your original demo, you can also add some text content which has very doubtful meaning but, in this very specific case, would need just a craeteTextNode, something again not really needed but the only thing that makes sense for a benchmark, so that the result is the one shown in this Code Pen, and the execution time here is 19.152ms, meaning you can show 10.000 buttons at 50FPS.
However, showing 10.000 buttons all at once has close to 0 use cases in the real-world, so you should rather understand what is hyperHTML, what it solves, and how to benefit from it, instead of using it as an innerHTML.
hyperHTML is 100% different from innerHTML, the sooner you understand this, the better it is.
If you need innerHTML, don't use hyperHTML.
If you want to use hyperHTML, forget any DOM operation that is not declarative, unless really needed, where this wasn't the case at all.
Related
I saw this article:
https://itnext.io/comparing-darts-loops-which-is-the-fastest-731a03ad42a2
It says that ".map" is slow with benchmark result
But I don't understand why slower than while/for loop
How does it work in low level?
I think it's because .map is called an unnamed method like this (_){ }
Can you explain that in detail?
Its because mapping an array will create a copy of each value than modify the original array.
Since a while/for loop does not copy the values but rather just accesses them using their index, it is a lot faster.
Can you explain that in detail?
It's like saying "I don't understand why hitchhiking on the back of a construction truck is so much slower than taking the high speed train to my destination".
The only detail that is important is that map is not a loop. map() internally probably uses a loop of some kind.
This person is misusing a method call that is meant for something else, just because a side-effect of that call when combining it with a call materializing the iterable, like toList(), is that it loops through the iterable given. It doesn't even have the side effect on it's own.
Stop reading "tutorials" or "tips" of people misusing language features. map() is not a loop. If you need a loop, use a loop. The same goes for the ternary operator. It's not an if, if you need an if, use it.
Use language features for what they are meant, stop misusing language features because their side-effect does what you want and then wondering why they don't work as well as the feature actually meant for it.
Sorry if this seems a bit ranty, but I have seen countless examples by now. I don't know where it comes from. My personal guess is "internet tutorials". Because everybody can write one. Please don't read them. Read a good book. It was written by professionals, proofread, edited, and checked. Internet tutorials are free, written by random people and about worth as much as they cost.
For MS Access 2010, I need a way to flexibly maintain the position and Z-order when a dozen forms are open. There can be multiple instances of the Parent form, and each one can lead to multiple instances of the Child form (some background here).
I want the user to be able to choose which form is top-most -- which means I don't want any forms set as Popup. Also, I want the Z-Order essentially preserved when a new Child opens. As the Child opens, the Parent loses the focus; at that point I'd like the Parent to drop back to its former position in the Z-order. I could add requirements along this line, but you get the idea ... I imagined a default behavior might do what I want, but if I have to assign Z-order locations from an array or something like that, I could accept that.
I also want to control the on-screen position of the Child forms (I mean only when they are first opened; they can be repositioned). If they open with the same X,Y coordinates, they'll appear stacked on top of each other and the user will have to reposition the top instance in order to see the others. That is inconvenient and, more important I think, disorienting.
So far I'm not able to have it all. I can get a nice cascade result by specifying X,Y positions, but it stops working when I use the flags to poke at the Z-order.
I've been using the API...
Declare Sub SetWindowPos Lib "user32" ( _
ByVal Hwnd&, _
ByVal hWndInsertAfter&, _
ByVal X&, ByVal Y&, ByVal cX&, _
ByVal cY&, ByVal wFlags&)
Global Const HWND_TOP = 0
Global Const HWND_TOPMOST = -1
SetWindowPos Hwnd, HWND_TOP, lngPosX, lngPosX, 0, 0, SWP_NOSIZE
I have different results when I try options for hWndInsertAfter& and wFlags&. Also when I set forms as Popup (results are better, but as mentioned, I want the user to bring any form to the top; therefore no Popup).
(Hmm... I bet Popup (and 'Modal`) are precisely what bring the API into best usage, because while a "must-answer" dialog is showing, control basically reverts to Windows. Confirm?)
My biggest frustration is that documentation for the API seems fragmentary and incoherent. And I wonder, am I stuck with that API? Is there something else I can use? I'd love a VBA solution apart from the API, but I guess this is what the API is for. Still, is there a method I'm missing?
I can post my variant attempts in more detail, but I feel I've been shooting in the dark, so I will wait on your feedback.
Update
I tried Reading The Manual. I tried twiddling with "form ownership" and NO/TOPMOST. For the Child form, I still have to choose between:
Being able to set the position upon opening
Being able to bring the Parent form back "on top" of the Child
Sorry for the late answer! I bumped into this while searching for a related issue.
One way to manage Z-order 'Access-only' is to use Form.SetFocus. The general solution outline:
Keep an array or collection of your form names and their Z-orders
When Z-order changes:
Resort your list to reflect the new Z-order
Turn screen updating off: Application.Echo False
Iterate through your list of forms in reverse Z-order. Use Form.SetFocus for each form. This will put the highest form on top.
Turn screen updating back on: Application.Echo True
This should work as long as all of your forms are non-modal.
If you need modal forms, be aware that they are by default on top, and you can only have one modal form open at a time. You can still use the above logic, just be sure to set Form.Modal = False for every form not on the top.
This is the 'how' answer, but I can't offer advice as to whether this is a sound approach for your application.
I believe the solution doesn't exist, or isn't worth pursuing because it would lean on Windows API libraries that may not be available in a few years. (This pessimism is not based on specific insights; but in general I see big pressures on the Windows user interface, so it's easy to imagine things shifting.)
I see some other hazards. Users will open numerous windows; resources will fail at some point, and probably before then they'll have lost any advantages from a human analytical point of view. Nonetheless they'll continue past the point of diminishing returns. Also I can expect to find a few pitfalls that gobble development time and lead in the end to complaints no matter how much time I spend mitigating them. Think "multi-user" and you'll know what I mean.
Instead, I need to re-think the approach. The application offers complicated and sometimes volumnous information. There's a way to do it. Not this way.
I might delete this OP, but it's gotten three up-votes, so I'll wait and see what you think. I can always punt to community wiki.
I'm fairly new to using Google Docs, but I have come to really appreciate it. The scripting is pretty easy to accomplish simple tasks, but I have come to realize a potential speed issue that is a little frustrating.
I've got a sheet that I use for my business to calculate the cost of certain materials on a jobsite. It works great, but was a little tedious to clear between jobs so I wrote a simple script to clear the ranges (defined by me and referenced by name) that I needed emptied.
Once again, worked great. The only problem with it is that clearing a few ranges (seven) ends up taking about ten full seconds. I -believe- that this is because the spreadsheet is being saved after each range is cleared, which becomes time intensive.
What I'd like to do is test this theory by disabling autosave in the script, and then re enabling it after the ranges have been cleared. I don't know if this is even possible because I haven't seen a function in the API to do it, but if it is I'd love to know about it.
Edit: this is the function I'm using as it stands. I've tried rewriting it a couple of times to be more concise and less API call intensive, but so far I haven't had any luck in reducing the time it takes to process the calls.
function clearSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
sheet.getRange("client").clear();
sheet.getRange("lm_group_1").clear({contentsOnly:true});
sheet.getRange("lm_group_2").clear({contentsOnly:true});
sheet.getRange("dr_group_1").clear({contentsOnly:true});
sheet.getRange("dr_group_2").clear({contentsOnly:true});
sheet.getRange("fr_group_1").clear({contentsOnly:true});
sheet.getRange("fr_group_2").clear({contentsOnly:true});
sheet.getRange("gr_group_1").clear({contentsOnly:true});
sheet.getRange("client_name").activate();
}
That is not possible, and will probably never be. It's not "the nature" for Google Docs.
But depending on how you wrote your script, it's probable that all changes are already being wrote at once, in the end. There's some API calls that may be forcing a flush of your writings to the spreadsheet (like trying to read after you wrote something), but we'd need to see your code to check that.
Anyway, you can always check the spreadsheet revision history to verify if it's being done at once or in multiple steps.
About the performance, Apps Scripts have a natural delay that is unavoidable, but it's not 10s, so there's probably room to improve on your script, using fewer API calls and preferring batch calls like setValues over setValue and so on. But then again, we'd have to see your code to assert that and give more helpful tips.
I am creating function (for example) to validate content, then if it is valid, close the view, if it is not, present further instructions to the user. (Or other such actions.) When I go to name it, I find myself wondering, should I call it -doneButtonPressed or -validateViewRepairAndClose? Would it be better to name the method after what UI action calls it, or name it after what it does? Sometimes it seems simple, things like -save are pretty clear cut, other times, and I can't thing of a specific example right off, but I know some have seemed like naming them after what they do is just so long and confusing it seems better to just call them xButtonPressed where x is the word on the button.
It's a huge problem!!! I have lost sleep over this.
Purely FWIW ... my vote is for "theSaveButton" "theButtonAtTheTopRight" "userClickedTheLaunchButton" "doubleClickedOnTheRedBox" and so on.
Generally we name all those routines that way. However .. often I just have them go straight to another routine "launchTheRocket" "saveAFile" and so on.
Has this proved useful? It has because often you want to launch the rocket yourself ... in that case call the launchTheRocket routine, versus the user pressing the button that then launches the rocket. If you want to launch the rocket yourself, and you call userClickedTheLaunchButton, it does not feel right and looks more confusing in the code. (Are you trying to specifically simulate a press on the screen, or?) Debugging and so on is much easier when they are separate, so you know who called what.
It has proved slightly useful for example in gathering statistics. The user has requested a rocket launch 198 times, and overall we've launched the rocket 273 times.
Furthermore -- this may be the clincher -- say from another part of your code you are launching the rocket, using the launch-the-rocket message. It makes it much clearer that you are actually doing that rather than something to do with the button. Conversely the userClickedTheLaunchButton concept could change over time, it might normally launch the rocket but sometimes it might just bring up a message, or who knows what.
Indeed, clicking the button may also trigger ancillary stuff (perhaps an animation or the like) and that's the perfect place to do that, inside 'clickedTheButton', as well as then calling the gutsy function 'launchTheRocket'.
So I actually advocate the third even more ridiculously complicated solution of having separate "userDidThis" functions, and then having separate "startANewGame" functions. Even if that means normally the former does almost nothing, just calling the latter!
BTW another naming option would be combining the two... "topButtonLaunchesRockets" "glowingCubeConnectsSocialWeb" etc.
Finally! Don't forget you might typically set them up as an action, which changes everything stylistically.
[theYellowButton addTarget:.. action:#selector(launchRockets) ..];
[theGreenButton addTarget:.. action:#selector(cleanUpSequence) ..];
[thatAnimatingButtonSallyBuiltForUs addTarget:.. action:#selector(resetAll) ..];
[redGlowingArea addTarget:.. action:#selector(tryGetRatingOnAppStore) ..];
perhaps that's the best way, documentarily wise! This is one of the best questions ever asked on SO, thanks!
I would also go with something along the lines of xButtonPressed: or handleXTap: and then call another method from within the handler.
- (IBAction)handleDoneTap:(id)sender {
[self closeView];
}
- (void)closeView {
if ([self validate]) {
// save and close
}
else {
// display error information
}
}
I've been working on a bit of JavaScript code that, under certain conditions, lazy-loads a couple of different libraries (Clicky Web Analytics and the Sizzle selector engine).
This script is downloaded millions of times per day, so performance optimization is a major concern. To date, I've employed a couple of flags like script_loading and script_loaded to try to ensure that I don't load either library more than once (by "load," I mean requesting the scripts after page load by inserting a <script> element into the DOM).
My question is: Rather than rely on these flags, which have gotten a little unwieldy and hard to follow in my code (think callbacks and all of the pitfalls of asynchronous code), is it cross-browser safe (i.e., back to IE 6) and not detrimental to performance to just call a simple function to insert a <script> element whenever I reach a code branch that needs one of these libraries?
The latter would still ensure that I only load either library when I need it, and would also simplify and reduce the weight of my code base, but I need to be absolutely sure that this won't result in additional, unnecessary browser requests.
My hunch is that appending a <script> element multiple times won't be harmful, as I assume browsers should recognize a duplicate src URL and rely on a local cached copy. But, you know what happens when we assume...
I'm hoping that someone is familiar enough with the behavior of various modern (and not-so-modern, such as IE 6) browsers to be able to speak to what will happen in this case.
In the meantime, I'll write a test to try to answer this first-hand. My hesitation is just that this may be difficult and cumbersome to verify with certainty in every browser that my script is expected to support.
Thanks in advance for any help and/or input!
Got an alternative solution.
At the point where you insert the new script element in the DOM, could you not do a quick scan of existing script elements to see if there is another one with the same src? If there is, don't insert another?
Javascript code on the same page can't run multithreaded, so you won't get any race conditions in the middle of this or anything.
Otherwise you are just relying on the caching behaviour of current browsers (and HTTP proxies).
The page is processed as a stream. If you load the same script multiple times, it will be run every time it is included. Obviously, due to the browser cache, it will be requested from the server only once.
I would stay away from this approach of inserting script tags for the same script multiple times.
The way I solve this problem is to have a "test" function for every script to see if it is loaded. E.g. for sizzle this would be "function() { return !!window['Sizzle']; }". The script tag is only inserted if the test function returns false.
Each time you add a script to your page,even if it has the same src the browser may found it on the local cache or ask the server if the content is changed.
Using a variable to check if the script is included is a good way to reduce loading and it's very simple:
for example this may works for you:
var LOADED_JS=Object();
function js_isIncluded(name){//returns true if the js is already loaded
return LOADED_JS[name]!==undefined;
}
function include_js(name){
if(!js_isIncluded(name)){
YOUR_LAZY_LOADING_FUNCTION(name);
LOADED_JS[name]=true;
}
}
you can also get all script elements and check the src,my solution is better because it hase the speed and simplicity of an hash array and the script src has an absolute path even if you set it with a relative path.
you may also want to init the array with the scripts normally loaded(without lazy loading)on the page init to avoid double request.
For what it's worth, if you define the scripts as type="module", they will only be loaded and executed once.