I don't know why the performance is so bad for you. Are you running 64-bit calibre? If not, then try that.
You can improve the performance of the two basic tests by using an advanced rule. Here is an example for Rating, replacing all 5 current rules.

The text in that box is:
Code:
program:
first_matching_cmp(
field('rating'),
0.1, '',
1.1, 'emoticon.png',
2.1, 'sceptic.png',
3.1, 'winking.png',
4.1, 'happy.png',
'in-love.png')
It works by comparing (rating < value) where value is 0.1, 1.1, etc, returning the string (file name) if the comparison succeeds. As such, the first comparison succeeds if rating is 0 (less than 0.1), and so on.
You would do something similar for the second one (Shelves) but using the "switch" function to set up the comparisons. Assuming that "Shelf" contains a single value (not like tags) then something like this would work.
Code:
program:
switch(
"read", "success.png",
"to-read", "play-button.png"
and so on. If Shelf is like-tags then you will need to do something different, probably using first_non_empty and in_list