art with code

2008-08-30

OCaml function usage stats

I.e. how many times a function name was written in all the .ml files on my system.
What you can use it for is optimizing the interface: make much-used names short, try to replace often-used code patterns with combinators.

E.g. the high scores for Array.unsafe_get and Array.length might mean that the idiom "for i = 0 to Array.length a - 1 do something (Array.unsafe_get a i); done" is common, while the relatively low scores for Array.map and Array.unsafe_set would suggest that the above iteration isn't really used as a map. So one could micro-optimize by making Array.unsafe_get shorter to write, or try to solve the root problem and find a better abstraction for iterating over arrays.


.() 2411
.[] 878
.() <- 599
.[] <- 232

Array.length 911
Array.unsafe_get 235
Array.create 213
Array.init 204
Array.make 161
Array.of_list 137
Array.map 136
Array.to_list 117
Array.unsafe_set 82
Array.sub 73

String.length 1240
String.sub 490
String.create 294
String.concat 287
String.make 168
String.blit 135
String.capitalize 52
String.unsafe_set 51
String.lowercase 51
String.unsafe_get 47

Filename.concat 171
Filename.check_suffix 89
Filename.basename 78
Filename.quote 56
Filename.dirname 54
Filename.chop_suffix 26
Filename.temp_file 22
Filename.current_dir_name 16
Filename.chop_extension 15
Filename.is_relative 14

List.iter 1538
List.map 1253
List.fold_left 436
List.rev 420
List.length 371
List.mem 248
List.fold_right 227
List.assoc 152
List.exists 131
List.filter 121

Str.regexp 92
Str.split 27
Str.global_replace 24
Str.string_match 19
Str.search_forward 12
Str.global_substitute 9
Str.matched_string 8
Str.matched_group 7
Str.regexp_string 6
Str.match_end 5

Sys.argv 170
Sys.time 75
Sys.file_exists 68
Sys.word_size 64
Sys.remove 51
Sys.getenv 42
Sys.max_string_length 41
Sys.os_type 30
Sys.max_array_length 27
Sys.set_signal 22

Unix.close 103
Unix.gettimeofday 97
Unix.time 69
Unix.openfile 64
Unix.file_descr 47
Unix.stat 31
Unix.write 21
Unix.read 20
Unix.getcwd 18
Unix.closedir 18


How-to:

def mk_hash; Hash.new{|h,k|h[k]=0}; end
hashes = %W(Sys Filename List Array String Str Unix).map{|n| [n, mk_hash] }

index_access = mk_hash

ruby_files = `locate '*.ml'`.split("\n").grep(/ml$/)
ruby_files.each{|f|
d = File.read(f)
hashes.each{|name, hash|
d.scan(/\b#{name}[\.:]+[a-z0-9_]+/).each{|k|
hash[k.split(/[\.:]+/).join(".")] += 1
}
}
s1 = d.scan(/\.\([^\)]+\)\s*<-/).size
s2 = d.scan(/\.\[[^\]]+\]\s*<-/).size
index_access[".()"] += d.scan(/\.\([^\)]+\)/).size - s1
index_access[".[]"] += d.scan(/\.\[[^\]]+\]/).size - s2
index_access[".() <-"] += s1
index_access[".[] <-"] += s2
}
(hashes + [["index_access", index_access]]).each do |n, h|
File.open(n+".txt", "w"){|f|
f.puts h.to_a.sort_by{|k,v| -v}.map{|k,v| k.ljust(25) + " " + v.to_s }
}
end

No comments:

Blog Archive