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
Post a Comment

Blog Archive

About Me

My photo

Built art installations, web sites, graphics libraries, web browsers, mobile apps, desktop apps, media player themes, many nutty prototypes, much bad code, much bad art.

Have freelanced for Verizon, Google, Mozilla, Warner Bros, Sony Pictures, Yahoo!, Microsoft, Valve Software, TDK Electronics.

Ex-Chrome Developer Relations.