Is “.first” faster or slower than “li.first”?
This blog post has some answers: Efficiently Rendering CSS
Is “.first” faster or slower than “li.first”?
This blog post has some answers: Efficiently Rendering CSS
Remember when I wondered how slow it is to copy data around in memory?
This time, I needed to load a 2MB file from disk and examine it for certain patterns.
The original from jazzy spell checker worked like this: It did a binary search in the file for a code. The code would be at the start of each line and be separated from the correct word by an asterisk:
AT*wide
AT*widow
AT*width
AT*wight
AT*wit
The search algorithm would seek somewhere in the file, skip the current line, read the next one, compare the code against the one we look for. If our code was smaller, we would seek backward; if it was larger, we would seek forward. Standard binary search.
Only it didn’t work. The test took 4 seconds to load the file without finding anything. Debugging recursive algorithms isn’t as nice as looking at them …
So I considered a different approach: I would load the whole file, character by character, and remember the lines with the same code in an index. A good time to have a look at NIO, especially the grep example.
Question: If it takes 4 seconds to seek ten times in a RandomAccessFile and read about 2000 bytes from it, how long would it take to read it character by character, examine each line, build an index and then load whole chunks (say, 1KB each) from the file when a word needs to be looked up? Plus the additional work of removing the code pattern from the chunk to produce a list of words …
Answer: 0.3 seconds. That’s more than ten times faster. And I could probably optimize the code some more.
Conclusion: When it comes to performance, measurement beats superstition.
And the new code is easy to understand, and to test, too! ^_^
It’s 2010, Firefox is going 4.0 soon and it still has no way to tell why it’s sluggish.
Yes, it would be nice if the FF developers could make the browser so fast that it would never become sluggish in the first place. I just fear that this is simply not possible with the current design. Look at Chrome: Every tab runs in it’s own process. So what if one of them is slow? All the other still feel crisp.
On FF, if one tab takes over the machine, you’re doomed. Yes, I could disable JavaScript and every add-on individually. Why bother? Starting Chrome solves the issue in no time.
If you care, support Bug 505104: Please add a tool to gauge Addon performance.
If you plan to measure the performance of your employees or to improve their performance with a bonus, then you should read this: How Hard Could It Be? Sins of Commissions.
If you’re like me and use Tomcat and you want to bring down the size of your WAR, you’re faced with one issue: All your applications need to use the same libraries (since there is only a single common/lib for everyone). So you’re either stuck with an old version or you need to upgrade all your apps at the same time. I just can see the budget guys shake their heads.
The solution is a list of directories in your context.xml which contain specific versions of the libraries you need. This way, you can install all the versions you need and each app can pick and choose.
For the complete solution, see the original article: Extending Tomcat WebappLoader to Share Library jars
OSS for teh win!
If you’re using Oracle and you have tables with foreign keys, then you must remember to add indexes to all the columns in the referenced tables (i.e. the foreign tables). If your schema has more than two tables, it’s hard to make sure all the necessary indexes exist. Fret no more and let Oracle do (most of) the work for you:
select table_name, constraint_name,
cname1 || nvl2(cname2,','||cname2,null) ||
nvl2(cname3,','||cname3,null) || nvl2(cname4,','||cname4,null) ||
nvl2(cname5,','||cname5,null) || nvl2(cname6,','||cname6,null) ||
nvl2(cname7,','||cname7,null) || nvl2(cname8,','||cname8,null)
columns
from ( select b.table_name,
b.constraint_name,
max(decode( position, 1, column_name, null )) cname1,
max(decode( position, 2, column_name, null )) cname2,
max(decode( position, 3, column_name, null )) cname3,
max(decode( position, 4, column_name, null )) cname4,
max(decode( position, 5, column_name, null )) cname5,
max(decode( position, 6, column_name, null )) cname6,
max(decode( position, 7, column_name, null )) cname7,
max(decode( position, 8, column_name, null )) cname8,
count(*) col_cnt
from (select substr(table_name,1,30) table_name,
substr(constraint_name,1,30) constraint_name,
substr(column_name,1,30) column_name,
position
from sys.user_cons_columns ) a,
sys.user_constraints b
where a.constraint_name = b.constraint_name
and b.constraint_type = 'R'
group by b.table_name, b.constraint_name
) cons
where col_cnt > ALL
( select count(*)
from sys.user_ind_columns i
where i.table_name = cons.table_name
and i.column_name in (cname1, cname2, cname3, cname4,
cname5, cname6, cname7, cname8 )
and i.column_position <= cons.col_cnt
group by i.index_name
)
Isn’t it a beauty? Thanks to Tom.
In my old post “The Space Between Two Characters“, I wrote about some flaws of WYSIWYG. Since then, I got some feedback.
The real issue behind the issues with WYSIWYG is that it doesn’t work while you edit the document. The concept is flawed, not the implementation. It is flawed because it omits some vital information that you need for editing. The information is omitted because it doesn’t make sense anymore as soon as you print the document on paper. And WYSIWYG means “if you don’t see it, you won’t get it.”
So it makes sense to omit feedback on where ranges start and end, what kind of break follows after a line, there the handles for a table are. But most WYSIWYG editors today have a “show invisible” option. Word can show you all those invisible characters so you can see “oh, this is a tab and not a space”.
For this to work, we need a tight integration between the editor model, the renderer and the view. The problem here is, as usual, performance. If you add all the hooks you need to be able to show nice visual feedback in the view, printing to a printer will be slower.
How much? Well, not much. Anymore. You’re quadcore will be 95% bored. It will need memory. How much? Well, to remember the bounding boxes for all letters rendered on the screen takes at most 4’608’000 bytes (“i”, 8px font, 30″ display with 3840×1200). That might seem like a lot but almost no PC sold next year will have less then 4GB of RAM, not even the Netbooks. My mobile phone comes with 32GB!
For printing, the values are usually much smaller. A normal page of text has around 1’500 to 2’500 characters per page and for printing, you just need to remember the current and maybe the next page (unless you need a page count but with todays CPUs, you can layout the pages twice).
So the final obstacles is code complexity. OO has helped a lot to cut down complexity in algorithms but there are problems which you can’t solve nicely with OO, for example “run this algorithm but replace line 5 with …” or “before … run …”.
AOP has come to solve this but it has failed to deliver so far. Maybe this is because point-cuts are too complicated to formulate, maybe because the debuggers can’t handle this case well, maybe because the setup is too complex or the resulting code is too fragile. Or because people are afraid of the leap of faith it takes to use it.