Is it possible to make Flutter 60FPS smooth, no matter how janky and slow my app currently is, using general-purpose and easy-to-use existing tools? - flutter

I have a Flutter app which is becoming more and more janky as time goes by and more features are added. Therefore, is there some utility to make it as smooth as 60FPS?
I know there are some official guides here: https://docs.flutter.dev/perf. However, I have tried to optimize and it is still slow. You know, some things just cannot be fast enough, such as long text, dynamic layout, necessary synchronous computations, etc. Especially when entering a new page or scrolling down a ListView. In addition, I have to use brainpower to find out what is slow and optimize when new features are added, so I hope there is some fully automatic thing which I can drop-in replace and forget it and it just works forever.

Disclaimer: I wrote this package and this is a Q&A style StackOverflow answer.
Yes, I have made it: https://github.com/fzyzcjy/flutter_smooth.
No matter how heavy the tree is to build/layout, it will run at (roughly) full FPS, feel smooth, has zero uncomfortable janks, with neglitable overhead. (I have made some benchmark reports here)
As for usage, for common scenarios, add 6 characters ("Smooth") - ListView becomes SmoothListView, MaterialPageRoute becomes SmoothMaterialPageRoute. For complex cases, use SmoothBuilder(builder: ...) and put whatever you want to be smooth inside the builder.
Roughly speaking about the implementation, it is done by submitting extra frames to the rasterizer every ~16ms, without disturbing all existing code. Therefore, the existing app code will almost not even know the existence of this package.

You need to check how do you use widgets, unnecessary rebuilds, some heavy operations when the widget is creating o rebuilding and it’s recommended to use the performance profiler in the devtools.

Related

Using GEGL with GTK 4 for a simple image viewer with pan/zoom support

I need a simple image widget with a support of panning/zooming but unfortunately it appears GTK still does not offer one. I have managed to achieve something similar by using a ScrolledWindow and a Picture backed by a PixBuf (via scaling the PixBuf on demand and a EventControllerMotion to mimic panning), but needless to say that this approach is too slow for smooth zooming on touchpads and uses an insanely high amount of memory due to no tiling.
A suggested approach seems to be using GEGL, but it's not obvious how one is supposed to do that. There seems to be helper libraries for previous versions of GTK (gegl-gtk and gegl-gtk3) but I do not know how one is supposed to use it with GTK 4 applications. And to be honest the documentations are pretty much non-existent.
So I would appreciate some examples/explanations on basics usages of GEGL within GTK (4) applications, or whether if there is a better way.

Which has better performance, symbols in the library or exported images of those symbols?

I recently chose to switch to a method where my library is totally empty and I embed every image/animation/sound that I need via the Embed tag because it would make my life easier. Having a lot of symbols in my library causes CS5 to run extremely slowly and it was really annoying me.
This was totally fine for making games for computers but I'm currently working on my first iPhone game and I'm noticing that the game starts lagging after a few seconds of play. It's not even a complex game but it does have a lot of images with transparency. So I'm wondering if it would run faster if I forget about the empty library method. I don't really know how that would affect performance but this is the first time that I have to worry about performance. But I am aware of other things that affect performance like transparency and object pooling (just read about this one).
Also the exact same game runs worse on an iPad even though it's a more powerful device?
Having images in your library means that Flash will compress them when it exports the SWF/SWC. This may or may not be desirable.
Using the [Embed] tag means that you can compress them yourself in something like Photoshop and have complete control over the output.
You say that your "game starts lagging after a few seconds of play". This seems to be a memory/design problem rather than whether or not your images are embedded through code or as library symbols. Do some profiling to see where you're spending most of your time, and to check that you don't have a memory leak.
Both using the library and the [Embed] metatags influence performance of your IDE, but they are evaluated at compile time and will produce just about the same byte code.
The performance of your game at runtime is an entirely different issue, though you might be able to get good results by rethinking which images to embed as bitmaps and which to use as vector sprites, how to organize larger images (e.g. creating one basic player sprite and adding individual looks by composition, instead of making each player variation a full sized animation) and trying to reduce the use of transparency and alpha masks.
There are many good articles about improving ActionScript performance both on the AVM2 and on iOS devices. Try searching for "ActionScript optimization runtime" - it should yield plenty of results.

XIB files vs. defining layout in code in iPhone

Aside from the WYSIWYG editor, what are the advantages of using XIB/NIB files over defining the layout in code in iPhone/iPad/iOS?
While I don't find XIB files much useful, many iOS developers do, which makes me suspect I might not know their benefits or how to use them properly.
Easier maintenance. More often than not, clients require last minute changes like changing the logo or changing colors or realigning something or some such. Much easier to change it in a xib file and see/show the results immediately
Decoupling. It forces you to write nicely decoupled code right from the offset, which again means easier maintenance.
Defining things in Interface Builder makes them much easier to adjust later. Also, doing interface elements in code can lead to a lot of code bloat, for setting things like exact placement, font, color, etc.
The main advantage using code directly gives you is speed. But it's usually better to start in IB and then see what might need speeding up.
Table cells are one of the main areas where you might consider drawing elements in code for speed.
Personnaly, I'm using XIB to see graphically my I'm doing so I don't have to run, check the look, change a bit the color, run the app, check... It allows me to get a better design. If you work with designer that gives you photoshop design, it will not be useful for you.
Second thing : when you start to really handle Xib, it's much faster than doing it with code (but it takes time and training for TableView and tableView cell for example)

Do I lose performance by using .xib files to provide an iPhone app's GUI?

I was wondering if there is a difference between using .xib files for GUI design and doing this programmatically.
As it is a compiler I would assume that there is no relevant time lost.
Am I wrong?
(Note: Tapping this out on my phone, so I apologize ahead of time for any weird formatting or grammar - if there are issues, I'll fix them when I'm back at my laptop.)
I've done some quick, dirty, and extremely informal tests to check this out for myself, and here's what I found (note that the app I built for the tests was just scratch and not necessarily representative of a "real" app):
Startup time was faster when when the initial screen was a nib
For all subsequent screens, performance increased when coding the UI by hand
It's odd at first, but when you think about it, maybe it isn't really all that strange.
The startup issue confuses me, but I assume it's because Apple, being Apple and being obsessed with startup times (in a good way, of course), just optimized the phone's unarchiver in such a way that loading from an archive (nib) can be faster than coding by hand.
That said, most people write apps that aren't going to be significantly affected by any differences. My (again: quick and dirty) tests showed that, from a cold start (you haven't run the app yet or in a while), the nib-based app consistently loaded its initial screen about twice as fast as the hand-coded version. While that sounds like a big deal, we're talking just a few milliseconds. That difference will be imperceptible to users. For a warm start (you've already opened and closed the app), the differences for startup time were much smaller.
For this reason, I like to use nibs for laying out the foundation of an app: any top-level navigation (tab controllers, nav controllers, etc.), and then code the rest of the UI by hand.
Plus, because the iPhone UI is so specific to, well, the iPhone (surprise!), coding UIs by hand isn't difficult the way it is when writing desktop apps. You use the same UI components over and over - once you've got that down, whipping up a UI in code is easy. You don't have eight-billion widgets to choose from as you would developing a Windows/OS X/whatever application. The iPhone's consistency makes it the easiest platform I've developed against in ages when it comes to hand coding UIs.
I've also found that NSCoding (which is what I use for persisting state across app runs) is much easier to work with when I've hand-coded a UI. I've run into problems where a nib-based screen wouldn't properly archive because of UIImage instances. UIImage (at least the last time I checked) doesn't conform to NSCoding, so the archive process dies (and a rather unpleasant death it is). I used UIImage as an example here, but anything the archiver tries to store that doesn't conform to NSCoding is going to foul up the process, so that's something to think about.
Another time I always code UIs by hand is whenever I'm using a dynamic table. If I'm creating a static table - one whose cells will basically never change - nibs are fine. For any other kind of table, and especially those that have, say, thumbnails and other resource-intensive bits, the control I get when coding by hand makes it possible to get performance you aren't going to get with nib-based table cells. For that, you do have to skip CocoaTouch and work directly with CoreGraphics, but the performance improvements you can make are worth every last line of code you have to write. For examples of table performance from projects I've worked on, see the Barnes and Noble Store (not the ebook reader) and Style.com. We built a framework for those (and other) apps, and the secret to the smooth table scrolling is that we never once used cells loaded from nibs (it's more complex than that, but skipping nibs was the first step to getting the performance you'll see in those apps).
Generally speaking, possibly the most important thing to consider when using nibs is that you need to break your UI up across files. That is, don't stick your app's entire UI into a single nib. When a nib is being loaded, it's the whole thing - there might be a view in the nib your users will rarely, if ever, see, and those get loaded just like everything else, sucking up resources for no reason. If you don't use separate nibs for each of your app's screens, it's easy to run into memory and performance issues.
To further clarify: if you have an app with five view controllers, stick each controller in its own nib. You don't want to load anything until its needed. There are exceptions to this, but that's simply how coding is - given enough time, you'll find a reason to do something "the wrong way," but the a-nib-for-each-screen approach is the way you ought to be doing it unless you have a good reason not to.
I'll leave it there - I hope it helps a little.
Just remember:
My informal mucking around showed that startup was faster with a nib (as long as you keep the nib as simple as possible, keeping only what you need in it).
After startup, performance seemed to improve for hand-coded UIs.
If done correctly, and if you aren't writing a game or something, nibs shouldn't result in perceptible performance issues.
In my experience, tables are different - they're one place I will rarely use nibs.
If you're using NSCoding for persisting app state, nibs can be problematic, and any workarounds probably aren't worth the effort since coding iPhone UIs by hand is relatively easy.
Keep your nibs as simple as possible - I can't say this enough. Wherever possible, create a nib for each screen of your app rather than stuffing your entire app's UI into a single nib.
Ok. Stopping for real this time.
Hope this helps :)
Very little. There are some exceptions. For example, if you use a xib to load the image that goes into a UITableViewCell, then that could be a problem since UITableViews with many cells are sensitive to loading times. However, for all intents and purposes, there should be no noticeable performance hit.
The information in the xib does have to be decoded at runtime and loaded into memory, which is not as fast as just creating UI elements programmatically and directly.
Beware premature optimization, especially when it involves writing a great deal more code than you need to.

How much does an CGAffineTransformMakeRotation() cost?

Is that an very cost-intensive function that sucky my performance away under my feet? I guess they used that one for the waggling buttons on the home screen + core animation. I just want to know before I start wasting my time ;)
Seems unlikely that it'd be much of a performance problem - it works out to something like a Cosine, a Sine, and a few multiplications. Don't call it thousands of times a second, and you'll be fine.
Very (very) little. This is also something you can easily measure yourself; see the following URLs for examples/information on implementing high-resolution timing:
http://developer.apple.com/qa/qa2004/qa1398.html
http://code.google.com/p/plinstrument/source/browse/trunk/Source/PLInstrumentTime.h
http://code.google.com/p/plinstrument/source/browse/trunk/Source/PLInstrumentTime.m
http://code.google.com/p/plinstrument/
Like with everything, it depends on how and how much you use it. It's used all the time in game development, which the iPhone is very well suited for. CoreAnimation is also very fast. If you're worried about it, my suggestion is to take one of the Apple-provided sample apps and run it through Instruments to preform some of your own benchmarks to see if they are acceptable for your needs.
All CGAffineTransformMakeRotation() does is fill in the matrix for a regular old CGAffineTransform. If you think you can fill (or pre-fill) the matrix faster yourself, then go for it (I'd be really surprised if this wasn't super-optimized already).
Then when it comes time to do the actual work of applying the transform, I'm pretty sure the GPU is told to take care of it so it'll run fast and your main CPU shouldn't take too much of a hit.
If you're really worried about it, then do the transforms in 2D space on top of OpenGL to make sure it's hardware optimized.
I just want to know before I start wasting my time
Optimise the system not the individual lines. Who knows how many times your code will call the transform. Better to get the whole system working, profile it and then optimise the parts that are too slow.
Don't worry about individual calls that people tell you are slow. Use this information as a pointer if your code is slow but always see how the operate in your code.