I'm developing a Magazine app and trying to find the best strategy to optimize performance and stability. The app should be able to handle +100 pages and expect users to swipe between them fast and smoothly.
With all this in mind, this is what I've tried so far.
The basic structure would be using tabs, with tabs bar hidden, to allow user swipe. Since loading + 100 tabs with huge images would be a mistake, I always mantain three tabs: the current page, the previous and the following. With a selection listener I change the positions accordingly.
The way I load and dispose images as selection changes is the big deal here. The app downloads the images from Internet and cache them in FileSystemStorage. Those images are 768 x 1024. This is what I've tried with different luck:
Simply retrieve the images from FileSystem everytime a new page is requested:
if (FileSystemStorage.getInstance().exists(rutaImagen)) {
try {
int size = (int) FileSystemStorage.getInstance().getLength(rutaImagen);
EncodedImage imagenPubli = EncodedImage.create(FileSystemStorage.getInstance().openInputStream(rutaImagen), size);
} catch(IOException io) {
}
}
This has proven to be inefficient and risky in terms of memory usage. My iPad mini launch frequent low memory warnings, and end up killed by jetsam after a little while.
Store the images in a WeakHashMap, so Images don't need to be constantly loaded form FileSystemStorage, which seems to be the cause of problems and too expensive. Only if they are garbage collected, the first method comes in action.
This solution perfoms better, and the memory warnings are dramatically reduced, but are still there. After stressing hard the app, 15 or 20 minutes later jetsam jumps in and kill the app.
Similar approach: instead of WeakHashMap, I have tried CacheMap. This has been the best solution for me so far. I have to push hard to see some memory warnings once in a while, and no crash so far. Still not enterily happy though, because I believe I should not see any memory warnings at all.
I talk about iOS only here because the app performs well on Android whatever method I use, and I have never got any Out of Memory there.
What do you think? Am I in the right path? Would you guys use a different approach?
Thanks
I believe that you should use the "let-it-be-done" approach. So far you have tried to code everything yourself, while codenameOne has many optimized way of doing it. The easiest way would be to use a MultiList, which will display your images (by using an UrlImage). The UrlImage will allow codenameone to handle the caching and else. Basically, the image will be loaded when viewed and placed in cache afterwards.
It's unclear from the question where the magazine page is just an image. If so I would suggest using the ImageViewer class as it was designed exactly with the use case of an infinite list of large images to swipe and zoom thru.
The general strategy with the Tabs seems like a good start if you need something more elaborate than images. If it doesn't perform well you can always substitute Tabs for something else.
Related
I have a react app that has many image references ( tags <img src=... /> and css background:url(...)) type.
These images are hosted on Azure Storage.
To speed up my App loading time on various devices (desktops and mobile), I need to resize these images before they hit the client, ie, on the server somewhere.
So far, I can think of the following options:
Pick each image, and produce multiple versions of them for various standard device sizes. Then, pick up each <img src=... /> tag, and, using JS alter the image name, such that the right size of image gets served. This will not work with css.
Use Azure CDN to automatically resize images. I was hoping that resizing would happen automatically, as the CDN portal retrieves the user-agent from the device. Does anyone know if this is true?
Serve images through an Azure function, resizing them on the fly (as suggested here)
Can someone suggest other options they can think of, or a pros / con of the above.
Since you're using javascript, use the window tag. For browsers, the window tab measures the resolution of the browser and you can set the height and width of your image to window.innerHeight and window.innerWidth. There are multiple other ways to do this but this is the easiest and most optimised if your coding project needs to be efficient with the least lines of code necessary.
More info about the window object here : https://www.w3schools.com/js/js_window.asp
P.S. this is only a solution for desktop, for mobile you can use screen.width, screen.height. This might not work on desktop but on a macOS Big Sur device it works, I tried it (This might be because macOS Big Sur is like a mobile optimised interface given that you can even run iOS apps on it but we don't know unless we try). That might be a better option as it is most likely common across all your devices.
More info about the screen object here : https://www.tutorialrepublic.com/faq/how-to-detect-screen-resolution-with-javascript.php
On the off-chance that none of them are common across all of your target devices, try making a detector program with which you can detect the device type and store that in a variable. Then create 2 if statements saying
if(deviceType = iOS){
<img src=..., screen.width, screen.height/>
}else if(deviceType = Windows){
<img src=..., window.innerWidth, window.innerHeight/>
}
Obviously this code won't work but it's just there to show you the flow where you can sort of understand what I meant. You need to integrate it your own way but this was just a way to make it easier as many times people mention that my answers are not easy to understand, just as a safety measure.
The best part of these options is that instead of remade copies of the image itself, this will resize the one, which saves storage space and eliminates the chance of the user using an unexpected display output like a 49" Samsung Odyssey G9 monitor where the resolution is extremely far from what you might have expected and resized. This also means you don't have to create a separate file just to make image resizing code, just the one to detect the OS (not necessary if the screen object works) which would've already been done since this is Azure we're talking about and they always detect their user base.
If you have any queries, please reply back.
Good luck!
We have a React website running with lots of high-quality images that has been experiencing this warning. How do you begin debugging this warning message on Safari? Is there specific things that cause this?
This message is caused by Safari watchdog process that monitors the Javascript scripts running on a page. It is there to notify the user when a script is utilizing too many resources. Your page when loaded on my computer raises the CPU utilization to 68 percent. Be weary of loops and custom render code.
Notes for improvement:
Make the rendering code as efficient as possible.
Combine the your internal Javascript files into a single file, instead of 7 files. Major improvement.
When possible(due to licensing and update considerations) include the 9 external scripts into the single file stated above. Minor improvement.
Split the main page into different sections either as separate pages or dynamically loaded using AJAX. Major improvement.
Avoid svg files. SVG files require a lot of computing power to rasterize and display. This is the main cause of the 7 second load times. Convert the files to png at the largest expected display resolution and offer an expanded SVG file if more detail is wanted(by click or delayed mouse over). Major improvement.
The number of images is not the issue. It is the number of SVG images(on load) and the scripts causing the issue.
Open the page in Chrome, open the Developer Tools and then switch over to the "Performance tab".
Then use the 2nd icon from the left - the one that looks like a "reload" button. Which says "Start profiling and reload page".
You will have a full rundown on what is taking how much. You can see in the top what is eating up FPS and CPU, and then you can select the timeframes that had especially high load.
In the bottom part then select the "Call Tree" or "Bottom-Up" tabs, to get a rundown of which scripts and function calls cause performance issues.
Usually "normal" websites ( e.g. not games ) would not have a lot of frame redraws. You can then spot for example if loading spinners are animated with javascript, instead of transforms and transitions; and sometimes they're still re-rendering although they are out of reach.
On a React specific note : It might also make sense to inspect it additionally with the React Developer Tools. E.g. you might be able to spot if sub-frames are re-rendering constantly for no reason.
Is there a way of creating ios native look like image grid, like e.g. in pinterest or beyond-shopping, with scrolling that doesn't jitter, lag, or stuck for couple of milliseconds? I've spent some time setting up InfiniteContainer, and try other approaches, used various kinds of layouts, but on ios it's still not looking as it should. Especialy on devices like new IPads PRO, this should be pretty smooth, but it's not...
A lot of the jittering happens because of IO that happens on the EDT, huge images scaled down or similar overheads (e.g. URLImage etc.). You need to benchmarks aggressively to understand what happens under the hood when you are using abstraction classes.
If you can create a simple test case with hardcoded images that jitters please file an issue with that so we can see what's wrong with the test case or fix a potential edge case bottleneck.
Here are the numbers
min+gzip 26k
gzip 90k
original 450+k
And React doesn't have many features in it's documentation. Why is it so big?
I have a feeling that it's the implementation of lightweight DOM. But I want to be sure.
React does quite a bit! The biggest nonobvious part of React is probably the events system -- not only does React implement its own event dispatching and bubbling, it normalizes common events across browsers so that you don't need to worry as much about it. For example, SelectEventPlugin is a built-in event "plugin" which provides an onSelect event which behaves the same way in all browsers.
The virtual DOM implementation does take a decent amount of code as well; a lot of effort is spent on performance optimization, which is why the unminified version includes ReactPerf, which is a tool for measuring rendering performance. In updating the DOM, React also does some convenient things for you like maintaining any input selection and keeping the current scroll position the same.
React also has a few other tricks up its sleeve. One of the coolest is that it fully supports rendering a component to an HTML string even if you don't have a browser environment, so you can send down a page that works even before JS is loaded.
What are you comparing React against? react-15.0.2.min.js is 43k (gzipped), but jQuery is 33k while ember-2.6.0.prod.js is 363k (also gzipped). Obviously these frameworks don't do exactly the same things but they do have a lot of overlap, so I think the comparison is reasonable.
If you're worried about download size, I wouldn't worry too much about JS code contributing to that. Here's an ad which I see on the right side of my Stack Overflow page right now:
Its download size is 95k -- I wouldn't think twice about including an image like that in a page because (even if I was worried about performance) there are usually so many other performance-related things to fix that are more lucrative.
In short, I don't think React is that big, and what size it does have comes from the many small things it does to help you out. You cite React's small API as a reason that React's code should be small, but a better question might be, "How is React's API able to be so simple given all the things it does for you?"
…but that's a totally separate question. :) Hope I answered your question -- happy to expand if I didn't.
A couple of thoughts.. I had some of the same concerns with it's size, but after using it, no joke, I would use it if it was 5MB in size. It's just that good. That said, I did decide to reduce as many dependencies on other libraries as possible. I was using jquery for two things.. ajax and the automatic ajax response and request handling (beforeSend, etc) that would handle when a token was in a response after login, and then make sure every ajax request added it to the Authorization header before sending. I replaced this with a super small simple bit of native javascript. Works great. Also, I was trying to use _underscore. I've replaced it with lodash, which is smaller and faster, although presently I am not using it so may remove it altogether.
Here is one article, of many on google, that I found that has some alternatives using native JS over jquery.
http://www.sitepoint.com/jquery-vs-raw-javascript-1-dom-forms/
I have a WPF application in which I'm using SoundPlayer to play several short sounds such as keyboard clicks. Sometimes, seemingly at random, the sounds will stop playing. When I navigate away from the page the sounds will then play all at once in one screeching playback.
My question is, are there any obvious reasons as to why this would happen?
I've tried several things but because I can't consistently reproduce the issue it's hard to find the cause. The sounds are used throughout the application, so I load them in app.xaml.cs into an application scoped static collection. I call SoundPlayer.Load() to ensure they're loaded into memory straight away.
Like I said, this never stops working completely. The play backs seem to pile up until navigating to another page where they all play at once.
One other thing that may have an impact is that I am displaying a webcam feed in the application. The webcam feed is loaded using the DirectShow.NET library. I'm not sure if loading graphs can have any adverse effect on the playback of sound.
I suppose the web cam is updating a UI element which will cause the UI thread to be pretty busy, in that case you probably do not want to use SoundPlayer.PlaySync() or SoundPlayer.Load which both block the current thread.
Instead try SoundPlayer.LoadAsync() and SoundPlayer.Play() which use a separate thread.