[Cs254f11] More performance issues with a particular function

Wm. Josiah Erikson wjerikson at hampshire.edu
Wed Nov 16 19:28:06 EST 2011


Hey guys,
     So I'm having a very serious performance issue with a particular 
function that I'm writing to find out what percentage of the notes in a 
given song are in a given scale.

So first, the relevant info to understand what I'm doing:

;Define some scales, relative
(def scales {
              :mixolydian '(0 2 4 5 7 9 10)
              :lydian '(0 2 4 5 7 9 11)
              :major '(0 2 4 5 7 9 11)
              :pentatonic '(0 3 5 7 10)
              :blues '(0 3 4 5 6 7 10)
              })

(defn score-against-scale
   "Compares the given note against scale (which should be a list of 
values) and key and returns 1 if it is in the scale, 0 if not"
   [note scale key]
   (count(filter #(= (mod note 12) (mod (+ %1 key) 12)) scale)))

;Then this takes forever:

(defn percent_in_mixolydian
   "Returns the percentage of real notes in the current song that are in 
the mixolydian scale,
    assuming that the most common note is the root"
   []
   (/
     (reduce + (map #(score-against-scale % (:mixolydian scales) (mod 
(most_common_real_note) 12))
        (get_real_notes (get_note_lines song))))
   (number_of_real_notes)))


Now, I've done a bunch of troubleshooting, and (most_common_real_note) 
returns quickly, as does (number_of_real_notes), and both of those 
functions actually also call (get_real_notes (get_note_lines song)), so 
that's not the issue - it's the

(map #(score-against-scale % (:mixolydian scales) (mod 
(most_common_real_note) 12))
        (get_real_notes (get_note_lines song)))

that takes forever. This returns immediately, since it creates a lazy 
sequence:

(def a (map #(score-against-scale % (:mixolydian scales) (mod 
(most_common_real_note) 12))
        (get_real_notes (get_note_lines song))))

But then if I do:

(def b (vec a))

To make it un-lazy, it never returns, or rather, it takes so long that I 
haven't let it return yet.

(count a)

Also takes forever, I suppose for the same reason. Some math:

(time (score-against-scale 4 (:mixolydian scales) (mod 
(most_common_real_note) 12)))
"Elapsed time: 26.771 msecs"

(number_of_real_notes)
12166

(/ (* 0.026 12166) 60)
5.271933333333333

Humph. So it will take 5.2 minutes just to run through my song and 
compare each note to the mixolydian scale? What am I doing wrong?

Thanks for any suggestions,
-Josiah




More information about the Cs254f11 mailing list