It says method chaining in D3.js performs several actions in single line of code. But i am not sure how much it cares about performance while executing.
For example,
By method chaining ,we would like to put the code like below:
var data =[10,20,30,40]
wrap.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x",function(d, j) {return scale(j); })
.attr("y",function(d,i){ return (h-d)})
.attr("width",scale.rangeBand())
.attr("height",function(d,i){ return (d)})
.style("fill","red");
In the above code,it will generate 4 rectangles, then for each 4 rectangles we are setting the attribute "x","y","width","height".
No.of rectangles ---> 4 No.of attributes("x","y","width","height")
---> 4 No.of iteration for each attribute ---> 4 (sine 4 rectangles) No.of iteration for 4 attributes ---> 4*4=16 times
Is it really necessary of such number of iterations?Is it fast performance?
Normally we do like this,
wrap.forEach(function(d,i){
d.setAttribute("x", scale(i))
d.setAttribute("y",(h-d))
d.setAttribute("width",w)
d.setAttribute("height",h)
})
In the above method ,No.of iterations used --> 4
So whats the advantage of d3.js method chaining and selection.daa with the above mentioned conventional approach
Please clarify me??
I was thinking about this today.
I think there is a fundamental problem with chaining.
Namely, you cannot partition data into different shapes that easily. And, if you could, you can't assume similar attributes chained from different shapes. A square and a circle say, have different attributes to define their size and location.
But, assigned from this conflict, which is not resolved by symbols, there remains the question, which you have asked,
"Is it an efficient representation?"
It make the code look nice. But, in fact each one is a function call that can go down a deep stack for anything to happen. And, that's slow.
So, one begins to think of an alternative similar to your loop. Or, perhaps the attributes can be gathered and assigned in one last shot - almost a compilation.
Don't forget that JavaScript is interpreted.
It is easy to get deceived into thinking that JavaSript will provide the efficiency you are looking for in certain applications. Of course, a tired user clicking on this and that would not notice the difference. But, there is the animation and the interaction of working parts when changes cascade in some way. Certain applications really need the efficiency.
Even the forEach that you are using can be suspect. I was working with a younger programmer last year, using D3. And, there was some part of one of our displays that ran woefully slowly. (A tired used would have certainly been awoken into a tizzy.) We took it out of the forEach and ran it in a regular "for" loop construct. Then, the same code ran with incredible speed. So, there are parts of JavaScript that are not as ready for prime time as you might think.
It is probably better to use many of the new constructs that are making their way into the language for many parts of an application. But, when it counts, you might wait for some update and use more optimized parts of the language.
I am fairly sure that d3 is not optimal in setting attributes. And, now I am trying to think of some better representation than chaining.
Remember the act of iterating itself is negligible. If the cost of setting an attribute was 1 you are comparing 16 * 1 with 4 * 4. Therefore it's not really a big problem. The chaining is a matter of concision.
Using Big O notation to analyse the algorithms, both are O(n).
Related
Quite a few months ago, I tried to find a way to place an element in the middle of an array of 3 items using the javascript sort function. It looked like there was no clever way of achieving that result.
However, I recently found a working solution to this problem.
I then tried to generalize this solution to a bigger array of (5, 7, 9, ...) items. But, it seems to break when the size of the array exceeds 10 items.
Since I found the solution through trial and error rather than pure thinking, I hope someone is able to explain to me why everything seems to work fine until this seemingly arbitrary number.
Here is Codepen demo I created to illustrate the issue : https://codepen.io/TMLN/pen/PBoKgR?editors=0011
You can edit the line ReactDOM.render(<Example items={example1} />... and replace the prop example1 by example2, example3, ... You'll see that everything starts breaking from example5 but I really can't figure out why...
PS : this works on Chrome but for those using Edge, you might encounter a bug due to the way the browser handles the sort function.
Your sort callback function returns 0 when neither of the compared values is equal to the value to be moved. You probably intended to indicate with this zero that the relative position of a and b (the two compared values) should not change, but actually the zero means that the sort implementation should consider the two values equal, and so it is actually free to swap their positions. Only when the implementation is (what is called) stable can you be sure that the relative position of the two values will not change.
Others have found that in Chrome the sort function is not stable, which explains the erratic behaviour you notice. See this Q&A for the situation, with regard to a stable implementation, in different browsers.
To make it work on all JavaScript engines you should change your code, and return a non-zero value for all pairs you compare, based on the index they currently occupy.
Final note: using sort for this task is a bad choice: a good sorting algorithm has O(nlogn) time complexity, but if you need to find indexes of values inside the sort callback you actually add a factor n to that, making it O(n²logn). To get an element out of an array and injecting it elsewhere is an operation that can be done in O(n) time. You can use Array#splice (twice) to do just that.
Right now I'm using plot.ly javascript library to visualise an array of numbers. I want to update this plot in every iteration. I tried to Plotly.newPlot('id',data); after values changed, however it takes time to re-define plot object every time.
I went through plot.ly documentation yet did not find a solution for my case.
I want to update graph in every interruption, maybe I need to update plot more 200 times after calling iterating function. Any solutions/suggestions for this problem? I can use another plotting library if there is one fits for this case.
Try Plotly.extendTraces
Unfortunately no official examples are available at the moment.
I'd recommend:
looking the source code here, and
the test cases here.
Bedi, unfortunately, I cannot respond to your comment directly. I don't have enough points (I need 50 and I have 15). Plotly.extendTraces() is what you need. The error you've noted is because update.y needs to be an array with a length equal to that of the indices argument to Plotly.extendTraces(). Looking at the source, indices is the third argument to the extendTraces. Your indices argument is only one item long ([0].length === 1). As long as itemList is an array of length 1 you should not be having a problem. Run console.log(itemList.length === [0].length) and I think you'll discover that you're trying to add too many points at once to your trace.
I currently have code that is pulling in data via jQuery and then displaying it using the each method.
However, I was running into an issue with sorting, so I looked into using, and added, jQuery's filter method before the sort (which makes sense).
I'm now looking at removing the sort, and am wondering if I should leave the filter call as-is, or move it back into the each.
The examples in the jQuery API documentation for filter stick with styling results, not with the output of textual content (specifically, not using each()).
The documentation currently states that "[t]he supplied selector is tested against each element [...]," which makes me believe that doing a filter and an each would result in non-filtered elements being looped through twice, versus only once if the check was made solely in the each loop.
Am I correct in believing that is more efficient?
EDIT: Dummy example.
So this:
// data is XML content
data = data.filter(function (a) {
return ($(this).attr('display') == "true");
});
data.each(function () {
// do stuff here to output to the page
});
Versus this:
// data is XML content
data.each(function () {
if ($(this).attr('display') == "true") {
// do stuff here to output to the page
}
});
Exactly as you said:
The documentation currently states
that "the supplied selector is
tested against each element [...]",
which makes me believe that doing a
filter and an each would result in
non-filtered elements being looped
through twice, versus only once if the
check was made solely in the each
loop.
Through your code we can clearly see that you are using each in both cases, what is already a loop. And the filter by itself is another loop (with an if it for filtering). That is, we are comparing performance between two loops with one loop. Inevitably less loops = better performance.
I created this Fiddle and profiled with Firebug Profiling Tool. As expected, the second option with only one loop is faster. Of course with this small amount of elements the difference was only 0.062ms. But obviously the difference would increase linearly with more elements.
Since many people are super worried to say the difference is small and you should choose according to the maintainability, I feel free to express my opinion: I also agree with that. In fact I think the more maintainable code is without the filter, but it's only a matter of taste. Finally, your question was about what was more efficient and this is what was answered, although the difference is small.
You are correct that using filter and each is slower. It is faster to use just the each loop. Where possible do optimise it to use less loops.
But this is a micro optimisation. This should only be optimised when it's "free" and doesn't come at a cost of readable code. I would personally pick to use one or the other based on a style / readability preference rather then on performance.
Unless you've got a huge sets of DOM elements you won't notice the difference (and if you do then you've got bigger problems).
And if you care about this difference then you care about not using jQuery because jQuery is slow.
What you should care about is readability and maintainability.
$(selector).filter(function() {
// get elements I care about
}).each(function() {
// deal with them
});
vs
$(selector).each(function() {
// get elements I care about
if (condition) {
// deal with them
}
}
Whichever makes your code more readable and maintainable is the optimum choice. As a separate note filter is a lot more powerful if used with .map then if used with .each.
Let me also point out that optimising from two loops to one loop is optimising from O(n) to O(n). That's not something you should care about. In the past I also feel that it's "better" to put everything in one loop because you only loop once, but this really limits you in using map/reduce/filter.
Write meaningful, self-documenting code. Only optimise bottlenecks.
I would expect the performance here to be very similar, with the each being slightly faster (probably noticeable in large datasets where the filtered set is still large). Filter probably just loops over the set anyway (someone correct me if I'm wrong). So the first example loops the full set and then loops the smaller set. The 2nd just loops once.
However, if possible, the fastest way would be to include the filter in your initial selector. So lets say your current data variable is the result of calling $("div"). Instead of calling that and then filtering it, use this to begin with:
$("div[display='true']")
I generally don't worry about micro-optimizations like this since in the grand scheme of things, you'll likely have a lot more to worry about in terms of performance than jQuery .each() vs. .filter(), but to answer the question at hand, you should be able to get the best results using one .filter():
data.filter(function() {
return ($(this).attr('display')==="true");
}).appendTo($('body'));
For a primitive performance comparison between .each() and .filter(), you can check out this codepen:
http://codepen.io/thdoan/pen/LWpwwa
However, if all you're trying to do is output all nodes with display="true" to the page, then you can simply do as suggested by James Montagne (assuming the node is <element>):
$('element[display=true]').appendTo($('body'));
I've been going through JS tutorials for a week and a half (Lynda.com, and HeadFirst series). Things make general sense, but JS is not nearly as easy for me as HTML/CSS. When I look at really simple, beginner, code (e.g. Lynda.com's tutorial where you create a bingo card), I'm struggling to really read through the code in terms of the representation of logical arguments. My guess is that if I don't tackle this rightaway any other language I try to learn will be impossible, not to mention that I won't learn JS well-- or at all.
So can anybody suggest a book/web site that offers good basic instruction about algorithms? OR, am I just being too impatient and after a couple weeks, things should settle and the code will make more sense.
Here is an example of the silly basic code that still preplexes.
function newCard() {
if (document.getElementById) {
for (var i=0; i<24; i++) {
setSquare(i);
}
HTML/CSS are document description languages, a way of representing visual structure and information, they are not programming languages as such.
JavaScript is not necessarily a simple language per se, so take it easy and you could do with an elementary programming introduction book.
Try to convert what you are reading to English, line by line, in order. The syntax, the symbols and the way it is written are probably the main source of confusion as you are not used to them. People who are not used to algebra panic at the sight of it, with cries of "I will never understand that, how do you read it?" - in time you will become accustomed.
Take this simple bit of code:
1 for (var i=0; i<24; i++) {
2 setSquare(i);
3 }
Line 1: a "for-loop"
A loop is a block of code (denoted by the braces {}) that is repeated until some point. In the case of a for loop, there are 3 settings (arguments) that control the loop.
The first is for initialisation, starting conditions, in this case setting the new variable i to 0, i=0.
The second is the condition it tells the loop whether to keep going and is checked every time the loop starts over. Here the condition is i < 24, keep going while the variable i is less than (<) 24.
The final part is an increment, whatever happens in the last part happens once per list. In this case at the end of the list, before the next loop. i++ means increment i by one, shorthand for i = i + 1.
So the loop is run multiple times, i starts at 0 and goes up by 1 each time, and once it is no longer less than 24, ie. it reaches 24, it ends. So the block of code is executed 24 times, with i = 0 to 23.
Line 2: Inside the loop is a single statement, a function call, to a function called setSquare, the value i is passed to it each time.
Line 3: The closing brace of the for-loop.
So all together, this code calls the setSquare() function 24 times, with values from 0 to 23.
What setSquare() does is a mystery without seeing that code as well.
Answering your question
It seems to me you're having some problems with basic programming constructs, such as functions, loops, variable declaration, etc - and if you don't understand those you're bound to never understanding any code at all. So my suggestion is to grab a book about programming (preferably about Javascript, in your case). I never learned JS from a book as I already had a programming background so the main concepts were already there, but a friend of mine liked O'Reilly Head First Javascript. Then, when the main concepts of the language are learned, take a look at the jQuery library.
Also, two quick notes:
HTML and CSS are not programming languages
You don't need to concern yourself with algorithms, at least for now - an algorithm is a series of complex procedures designed to solve a specific problem, and not a simple for loop used to iterate an array :)
You find learning JavaScript harder than the other two more difficult because it is a programming language where as CSS and HTML are markup/styling.
JavaScript isn't an easy first language to learn either. I wouldn't be too worried if you find yourself confused, programming is hard and it doesn't come naturally to everyone. Eventually, your mindset will change and things that seemed impossible at first will seem very intuitive.
That being said, there are very few good starting resources to learn JavaScript. Your best bet is to look at a book like Head First JavaScript. They will take a very slow progression through how to program (the mentality of writing algorithms to solve problems) and also introduce you to all of the features of JavaScript.
Keep your head up : ).
I would hope that you're not having trouble with the for-loop as that's fundamental to programming.
1 for (var i=0; i<24; i++) {
2 setSquare(i);
3 }
To follow up on on #Orbling's detailed answer, line 2 reveals the main point of the program. Assuming that setSquare(i) means what it says, the for loop apparently has the side effect of changing the state of a square to the current value of i in a for loop. My guess is that the width of the square changes with i.
A key team I mentioned is "side effect", which means that a program will affect the state of another entity outside of itself. The following for loops also has a side effect.
1 for (var i=0; i<24; i++) {
2 print(i);
3 }
where I will stipulate that print(i) will render the value of i in a JS popup.
I am rendering around 3000 records,
i am using this sorting open source script ,
When i click the column, my browser getting hang very shortly ,
i cant able to continue,
Is there any solution for this prob.
link text
Update 2
I sent my updates to the original author of the above code, but until he decides to post it, here is my updated version. It speeds up the use of the standard built-in sort() if you decide to do that. It also replaces the stable cocktail sort with a stable merge sort. The merge sort is nearly as fast as using sort() in my tests. I hope that helps.
Update
I no longer think that there is a great discrepancy between browsers as far as the built-in sort() function is concerned. While IE8, for instance, is much slower overall than say Chrome, I don't think that it has to do with just the sorting function. I did some profiling in IE8 using some random data. I found that the original code can be improved quite substantially when the column data is numeric or a date. Putting the regexp searches in the comparison functions for these data types slows things down a lot because they are being every time a comparison is done between elements which for 3000 elements is around 60,000 comparisons. The number of regexp's is twice that. By doing all of this before we start sorting, we do 3,000 regexp's rather than 120,000. This can be about a 50% savings in time. I'll submit my changes to the sorttable code in a little bit.
Other than that, most of the time is reordering the DOM elements around, not sorting (unless you are using the shaker sort). If you can find a faster way to do that then you can save some time there, but I don't know of any way to do that.
Original answer:
The problem here may have to do with the actual sort. If you uncommented some of the code there (and commented out some other code), then your code is using a shaker sort to get a stable sort. Shaker sort is essentially a bidirectional bubble sort. Bubble sorts are very slow, O(N^2). If you didn't uncomment that code, then it is using javascript's built-in sort() function with various comparator functions. The problem with this is that this sort() function is implemented differently in different browsers so you might want to see if this problem happens in some browsers and not in others. Apparently, the Webkit code still uses a selection, or min, sort which is O(N^2). That almost makes me want to cry. What browser have you been using to test this?
If the sort function turns out to be the problem, then you might try changing the above code to sue a merge sort or quicksort which are both O(N log N). Quicksorts are a little bit more tricky to avoid O(N^2) cases so you might want to stick with merge sort. Also, merge sort is a stable sort. This page has an example to get you started with merge sort.
You have answered your own question in a way.
Take a look at the sorting script.
Sorting 3000 records, rearranging the DOM and rendering the output.
It will for sure take time.
This script you are using is meant for small sets of records.
Suggestion: Using server side sorting and render the results in pages, each page containing say 50 records. For about 3000 records, you will have around 60 pages.
Lets say you are on the 45th page. Then you fire a SQL query to sort (asc/desc) and skip the first 44*50 records and retrieve the next 50 records (for 45th page).
This library seems to use DOM manipulations to sort.
It would be better to generate the table each time and inject it using innerHTML.
In today's javascript engines this looks instantaneous.
Even IE6 is good at that.
That being said... showing 3000 lines to a human is something questionable.But this is another debate ;)