Skip to content

Instantly share code, notes, and snippets.

@greggirwin
Created August 5, 2019 22:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save greggirwin/0305173d962224fbdf59144087b0fe98 to your computer and use it in GitHub Desktop.
Save greggirwin/0305173d962224fbdf59144087b0fe98 to your computer and use it in GitHub Desktop.
Red Load-Time and Type Tally
Red [
file: %load-time-type-tally.red
purpose: {
Load a Red file, noting how long it takes to do so,
then parse it and tally all the values by datatype.
It's not a metric that may prove useful, but in
aggregate, we could see what types are most commonly
used.
I'll correct my own thinking. After just a few sample
runs on files, there is a clear pattern in what types
appear in sorted order across scripts. This could tell
you not only whether a script has a "normal" distribution
of types, but could also lead to further analysis of
what the focus of some code is, based on its type
distribution.
}
]
; from %profile.red
delta-time: function [
"Return the time it takes to evaluate a block"
code [block! word! function!] "Code to evaluate"
/count ct "Eval the code this many times, rather than once"
][
ct: any [ct 1]
t: now/time/precise
if word? :code [code: get code]
loop ct [do code]
now/time/precise - t
]
count-type: func [type [word!]][
; Results is a map!. If there's no entry for a type yet,
; results/:type returns none, which `+` doesn't like, so
; we have to check for that, to prime each entry.
either results/:type [
results/:type: results/:type + 1
][results/:type: 1]
]
;-------------------------------------------------------------------------------
; This is where our tally results go
results: #()
; Main parse rule
type-tally-rule: [
some [
; If we see a block coming up, count it, then parse into it,
; using this rule
ahead block! (count-type 'block!) into type-tally-rule
; For any other value, count it by datatype. We use the word
; for a type, because maps can't use datatype! values as keys.
| set val any-type! (count-type type?/word :val)
]
]
;file-filter: ["Red files" "*.red" "Red System Files" "*.reds" "Rebol Files" "*.r"]
file-filter: ["Redbol files" "*.red;*.reds;*.r"]
; Keep asking for new files to process, until they don't select one.
while [file: request-file/file/filter what-dir file-filter][
load-time: delta-time [blk: load file] ; Track load time
clear results ; Self-explanatory
parse blk type-tally-rule ; This does all the work
print ["File:" mold file "Time to load:" load-time] ; Show top-line info
; This is all you really need
;print ["Contents:" mold results] ; Show detailed tally results
; But if you want to sort the results, you have to conver to a
; block, as maps can't be sorted. /skip 2 means treat the block
; like key-value pairs. /compare 2 means sort by the second element
; (the tally value). /reverse means higher numbers first.
res-blk: sort/skip/compare/reverse to block! results 2 2
; One more thing, we want it formatted nicely, but converting
; from a map doesn't do that for us. So we'll set our own
; new-line markers every 2 elements.
new-line/skip res-blk on 2
print ["Contents:" mold res-blk]
]
; Halt, so the console showing the results doesn't close.
halt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment