Echarts custom series are really flexibel and convenient.
But unfortunately the performance is really slow (compared to the "native" series).
e.g. here is a jsfiddle example (using echarts 4.8.0) that draws 5 custom series (with only 500 points each).
To test with more data, you can simply adjust the variables at the top of the jsfiddle code:
/**
* the number of data-samples
*/
var dataCount = 2000;
/**
* we create one custom series for each item in the csColors array
*/
var csColors = [
'#FF9800', '#9C27B0', '#512DA8', '#4CAF50', '#448AFF'
// , '#d32f2f', '#F1C40F', '#8bc6ff', '#00bc91', '#992f1c'
];
Even with this little data, zoomig (using the mouse wheel) or using the brush is already really slow.
For our application we would need up to 10 charts with ~5 series and 1k data samples each. And with that many samples the custom series is just not usable, because rendering takes way too long.
Any ideas how we could improve the performance?
e.g. when we use the brush it seems that almost every mouse-move redraws the whole series: I guess it may be related to the emphasis settings: is there a way to deactivate this?
Or is there maybe another way we could get fast custom series (i.e. directly draw on the canvas, ..)?
Related
I am exploring using a GAS script to build a human-readable product catalogue as a Google Spreadsheet, it's easy to generate a PDF or print from there. The product data is all quickly accessible via an API including image URLs for each product.
I'm running into issues because inserting an image which references a URL, then re-sizing it takes 3-4 seconds in my prototype, and I might have 150x products. Runtime is capped at 6 minutes. Here's a simplified example of the image processing loop that I'm imagining:
function insertImages(sheet, array_of_urls) {
for (var i in array_of_urls) {
let image = sheet.insertImage(list_of_urls[i], 1, (i+1)*3);
image.setWidth(90);
image.setHeight(90);
}
}
I think it takes so long because of the interaction with the UI. Can anyone recommend a way that I could make the script functionally efficient?
Insert images over cells:
If you want the images over cells (that is, not contained in a specific cell), I don't think there's a way to make this significantly faster. There's no method to insert multiple images at once.
You could at most try to retrieve the image blobs, resize the images through some third party before inserting them, and finally insert them via insertImage(blobSource, column, row).
In any case, there are ways to get through the 6 minute execution time limit. See, for example, this answer.
Insert image in cells:
If you don't have a problem having the images in specific cells, and not over cells, I'd suggest adding the images via IMAGE formula, using setFormulas.
The image size can be set through the IMAGE formula, the following way:
=IMAGE("URL", 4, [height in pixels], [width in pixels])
Also, to make sure the cells' height is large enough for the images to be seen, you can use setRowHeights.
Code snippet:
function insertImages(sheet, array_of_urls) {
const formulas = array_of_urls.map(url => ["=IMAGE(\"" + url + "\", 4, 90, 90)"]);
const firstRow = 1;
sheet.getRange(firstRow,1,formulas.length,formulas[0].length).setFormulas(formulas);
sheet.setRowHeights(firstRow, formulas.length, 90);
}
This answer provides a nice way to make smooth animations in SciLab. I now have to write a simulation of a body attached to two strings (and therefore its movement regarding some additional forces).
The code in the link works well to render movement of a single point and, unfortunately, I didn't manage to make an animation of a point + two lines using this method. If someone is curious, I tried this code to do it:
frametime=(tk-t0)/Nt//defining the waitnig time
plot(Y(1,1),Y(2,1),"o")//plotting the point
plot([0;Y(1,1)],[0;Y(2,1)],style=1)
plot([D;Y(1,1)],[0;Y(2,1)],style=1)//plotting the two initial lines
h1_compound = gce();
h_point=h1_compound.children
h_point.mark_size = 20;
h_point.mark_background = 2;
h_line1=h_compound.children
h_line2=h_compound.children
//h_axes = gca();
//h_axes.data_bounds = [0,-1;10,1];
realtimeinit(frametime);
for i=1:Nt//my vectors have Nt points
realtime(i);//wait "frametime" seconds before drawing the new position
h_point.data=[Y(1,i),Y(2,i)];
h_line1.data=[[0;Y(1,i)],[0;Y(2,i)]]
h_line2.data=[[D;Y(1,i)],[0;Y(2,i)]]
end
The question is: is there any way to make an animation of three shapes without making axes blink (as it is with the window refreshment) or other wierd stuff?
Since you didn't create a MCVE I can't reproduce your exact problem. But you may try to add drawlater(); before, and drawnow(); after your data modification to see if it does help with blinking or not.
Or you may get much better looking result by saving your plots in every round with xs2gif and assemble the animation with another gifmaker progam (there are free online sites to do this, however with some limitations). If you need to present your result, you should do this step anyway.
EDIT: The original question is still contained below, but I decided to re-title to a form that will be more useful to developers in a variety of cases, some of which described in my answer below, as the solution to the original problem turned out to provide a much wider area of application.
I have a set of greyscale icons for an application, and a requirement that the icon color can be changed by the user.
So, the obvious solution is to use the stock Colorize element from QtGraphicalEffects.
The effect itself has a cached property - which caches the result of that particular effect so that it is not continuously calculated. However, this only applies to that particular instance of the effect, meaning if there are multiple icon instances, and every one has a colorize effect, this cache will not be shared between the different instances.
Obviously, one single cache would be enough, considering that all icons are the same size and color, that data from VRAM can be reused, saving on VRAM and GPU time.
So the big question is how to reuse that single cache of that single effect and display it multiple times without any overheads.
Also, the previous question is regarding the current course I've taken with colorizing icons. However, there might be another approach I am missing.
Naturally, efficiency is key, but simplicity is also desired, I mean I can think of several low level ways to do that very efficiently, but they all require more complex low level implementations, they are not possible to do in QML.
The solution turned out to be unexpectedly simple.
In the case, specific to the OP - that is colorize icons, the most efficient way is to simply use a custom ShaderEffect with a trivial fragment shader - set gl_FragColor to the desired color, passed as a vec4 and the alpha value from the source image. There is really no need to cache anything, as the shader is really simple and fast, as fast as it gets.
There is only one thing to consider - the possibility that the QML scenegraph might allocate the original image in a texture atlas, the default implementation will then copy the texture from the atlas to another texture. We do not want this as it defeats the purpose - VRAM usage will rise, as this will be done for every "instance" and there is also the possibility that the newly allocate textures will be larger than they need to be, since on some platforms, there is a limitation to how small a texture can be, and in this case we are talking icons, so they won't be all that big.
The solution is to explicitly set supportsAtlasTextures to true. This means you must also pass the offset of the texture in the atlas and calculate the offset - still very little overhead. This will ensure efficiency, textures from atlases will not be duplicated in memory, and furthermore, the render engine will actually allow different shader effects using different texture from the same atlas to be batched together in one call.
A similar approach can be used to cache pretty much anything, and use that cache to display an "image" - use a ShaderEffectSource to "capture" the desired image, and then use a ShaderEffect with an even more trivial fragment shader - simply output the data from the source sampler. Several extremely useful use-cases immediately come to mind:
it can be used to "instantiate" images, the result of computationally intenssive shaders, keep in mind that ShaderEffectSources and ShaderEffects can be chained in arbitrary order
it can be used to instantiate procedurally generated images, once again using shaders, such can be used as tiling textures, and even animated very efficiently
it can be used together with a QML Canvas to use a complex canvas drawing as a cache and source for multiple "images"
it can be used as an image, produced by the composition of complex QML Items - those are actually quite heavy on RAM, imagine a scenario where you have a 1000 objects, and each of them is made out of 20 different QML items - rectangles, texts, images, god forbid animations, that's 20000 object in memory - that's like 500 MBs of RAM usage based on my tests, but if they are identical, a single object can be used to provide cache, and all the other objects can only use a single shader effect to display that cache. It has implications on CPU time as well - say your design is bound to changing values - a very usual scenario, if you have 20000 objects in memory, that's 20000 evaluated bindings - even for trivial expressions this may take several seconds on a mobile device, freezing the screen for that duration. Caching that will reduce the freeze time 1000 times, practically to non-existent.
it can can also be used to cache and instantiate animations, significantly reducing the needed CPU time, and also it can work with video as well
What I did to optimize QtGraphicalEffects was using Item.grabToImage() :)
This function returns QQuickItemGrabResult item which has url() function. This function returns an QUrl which can be set as a source for an Image object.
So what you need to do is create one Image with Colorize applied on it. When it is ready use grabToImage() and after successful grab save the QUrl somewhere safe and destroy the source object.
I suppose that you will need to change the color of the icons from time to time while the application is running. If so keep in mind that just changing the source of the Image objects so that no one uses grabbed image url will make it be released from memory. Not instantaneously but when it is needed.
Because of some incompability my applications only manage the memory correctly if I use QGuiApplication::setAttribute(Qt::AA_UseOpenGLES); in main.cpp file.
Also here is an important fact:
Images are cached and shared internally, so if several Image items have the same source, only one copy of the image will be loaded. (source)
Here is working example. The source object is Rectangle but it can easily be changed to an Image.
import QtQuick 2.3
import QtQuick.Window 2.2
import QtGraphicalEffects 1.0
Window {
visible: true
width: 500
height: 500
property string urlOfMyIcon: ""
Grid {
columns: 1
spacing: 10
Image {
width: 100
height: 100
source: urlOfMyIcon
}
Image {
width: 100
height: 100
source: urlOfMyIcon
}
Image {
width: 100
height: 100
source: urlOfMyIcon
}
}
Component.onCompleted: {
component.createObject(this)
}
Component {
id: component
Item {
id: yourImageWithLoadedIconContainer
Rectangle {
id: yourImageWithLoadedIcon
width: 80
height: 80
color: "white"
visible: false
// needed because I used Rectangle instead of Image
Component.onCompleted: {
colorizeEffect.grabToImage(function(result) {
urlOfMyIcon = result.url;
yourImageWithLoadedIconContainer.destroy()
}, Qt.size(width, height));
}
// use this when using Image instead of Rectangle
// onStatusChanged: {
// if (status === Image.Ready)
// colorizeEffect.grabToImage(function(result) {
// urlOfMyIcon = result.url;
// yourImageWithLoadedIconContainer.destroy()
// }, yourImageWithLoadedIcon.sourceSize);
// }
}
Colorize {
id: colorizeEffect
anchors.fill: yourImageWithLoadedIcon
source: yourImageWithLoadedIcon
hue: 0.8
saturation: 0.5
lightness: -0.2
visible: false
}
}
}
}
I need to selectively show/hide 1000+ lines of different sizes, positions and colors.
My first attempt made a THREE.Geometry with a name for each. To hide/show I iterate over scene and hide/show on each based on name and my heuristic. That seemed very slow - around 50Hz for ~1000 lines.
I made a test using a similar approach but using only a single THREE.Geometry to hold all of the lines. That was much faster but of course but I can only apply one material to all the lines which is no good. I was able to set the right flags and update the positions of the lines while the app was running though.
The best approach seems to be to use THREE.BufferGeometry. I made a test which was very fast and worked as expected for the initial set up but I was unable to change the position/visibility and color of each line afterwards. I made a JS fiddle that illustrates it - http://jsfiddle.net/SSnKk/ - but calling buffer_geometry.dynamic = true; and buffer_geometry.verticesNeedUpdate = true; didn't appear to help.
If you update the contents of the attribute buffers, you need to set the needsUpdate flag. For example:
buffer_geometry.attributes.position.needsUpdate = true;
buffer_geometry.attributes.color.needsUpdate = true;
three.js r.143
First of all, I know that displays lists were deprecated in OpenGL 3.0 and removed on 3.1. But I still have to use them on this university project for which OpenGL 2.1 is being used.
Every article or tutorial I read on display lists use them on some kind of object that is drawn multiple times, for instance, trees. Is there anything wrong in creating one list for a single object?
For instance, I have an object (in .obj format) for a building. This specific building is only drawn once. For basic performance analysis I have the current frames per second on the window title bar.
Doing it like this:
glmDraw(objBuilding.model, GLM_SMOOTH | GLM_TEXTURE);
I get around 260 FPS. If you don't about the GLM library, the glmDraw function basically makes a bunch of glVertex calls.
But doing it like this:
glNewList(gameDisplayLists.building, GL_COMPILE);
glmDraw(objBuilding.model, GLM_SMOOTH | GLM_TEXTURE);
glEndList();
glCallList(gameDisplayLists.building);
I get around 420 FPS. Of course, the screen refresh rate doesn't refresh that fast but like I said, it's just a simple and basic way to measure performance.
It looks much better to me.
I'm also using display lists for when I have some type of object that I repeat many times, like defense towers. Again, is there anything wrong doing this for a single object or can I keep doing this?
Using display lists for this stuff is perfectly fine and before Vertex Arrays were around they were the de-facto standard to place geometry in fast memory. Put display lists have a few interesting pitfalls. For example in OpenGL-1.0 there were no texture objects; instead placing the glTexImage call in a display list was the way to emulate this. And this behaviour still prevails, so binding a texture and calling glTexImage in a display list will effectively re-initialize the texture object with what's been done in the display list compilation, whenever the display list is called. On the other hand display lists don't work with vertex arrays.
TL;DR: If your geometry is static, you don't expect to transistion to OpenGL-3 core anytime and it gives you a huge performance increase (like it did for you), then just use them!