Last active
December 15, 2015 00:29
-
-
Save snodgrass23/5173452 to your computer and use it in GitHub Desktop.
speed test comparisons for Node and Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function getRands(i) { | |
var r = []; | |
while (i--) { | |
r[i] = Math.floor(Math.random() * 5); | |
} | |
return r; | |
} | |
function findMatchScore(profileDimensions, verseDimensions) { | |
var i = profileDimensions.length; | |
var diff, total = 0; | |
while (i--) { | |
diff = (profileDimensions[i] - verseDimensions[i]); | |
total += diff * diff; | |
} | |
return total; | |
} | |
function randomMatch(profile) { | |
var verse = getRands(25); | |
var score = findMatchScore(profile, verse); | |
//console.log('score:', score); | |
} | |
function timeIt(i) { | |
var profile = getRands(25); | |
console.log('Matching profile:', profile); | |
while (i--) { | |
randomMatch(profile); | |
} | |
} | |
function testIt() { | |
var a = [0, 0, 0]; | |
var b = [0, 0, 0]; | |
var c = [4, 4, 4]; | |
console.log('should be 0:', findMatchScore(a, b)); | |
console.log('should be 48:', findMatchScore(a, c)); | |
} | |
timeIt(1000000); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def rand_n(n, max) | |
randoms = [] | |
n.times do | |
randoms << rand(max) | |
end | |
randoms | |
end | |
def diff_score(a, b) | |
(a - b) * (a - b) | |
end | |
def match_score(a, b) | |
score = 0 | |
a.length.times do |i| | |
score += diff_score a[i], b[i] | |
end | |
return score | |
end | |
user = rand_n(25, 4) | |
1000000.times do | |
message = rand_n(25, 4) | |
match_score user, message | |
end |
○ → ruby-prof revised.rb
Thread ID: 70306702427860
Fiber ID: 70306722876660
Total: 211.227834
Sort by: self_time
%self total self wait child calls name
28.40 76.478 59.991 0.000 16.487 25000000 Object#diff_score
17.98 54.562 37.980 0.000 16.582 25000025 Kernel#rand
16.68 89.800 35.238 0.000 54.562 1000001 Array#initialize
7.85 16.582 16.582 0.000 0.000 25000025 Kernel#respond_to_missing?
7.81 16.487 16.487 0.000 0.000 25000000 Fixnum#**
1.49 115.298 3.141 0.000 112.157 1000000 Object#match_score
1.25 211.228 2.647 0.000 208.580 1000001 *Integer#times
0.90 93.282 1.897 0.000 91.385 1000001 Object#rand_n
0.75 91.385 1.585 0.000 89.800 1000001 Class#new
0.00 211.228 0.000 0.000 211.228 2 Global#[No method]
0.00 0.000 0.000 0.000 0.000 2 IO#set_encoding
0.00 0.000 0.000 0.000 0.000 3 Module#method_added
* indicates recursively called methods
Just for fun, I wrote a go implementation:
package main
import (
"math/rand"
)
func main() {
user := generateRand(25, 4)
for i := 0; i < 1000000; i++ {
numbers := generateRand(25, 4)
matchScore(user, numbers)
}
}
func generateRand(n int, max int) []int {
numbers := make([]int, n)
for i := 0; i < n; i++ {
numbers[i] = rand.Intn(max)
}
return numbers
}
func matchScore(user []int, numbers []int) int {
score := 0
for i, _ := range user {
score1, score2 := user[i], numbers[i]
score += (score1 - score2) * (score1 - score2)
}
return score
}
○ → time go run revised.go
real 0m1.765s
user 0m1.723s
sys 0m0.040s
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I am not a Ruby expert but I have a couple of suggestions.
In the Ruby Array you can just do array differences. So for instance instead of
you could do
This only shaves off a few seconds though.
I think the bigger issue is the test itself. I believe v8 engine has been highly optimized for mathematics ops (more like a hunch here than any real evidence). So in your test here you are calling
rand
andMath.random()
25 million times. That is a lot of calls to function that could be implemented very differently in the two interpreters.I might change the test instead to more closely mimic your end goal. Perhaps generate a sample text files with 1000000 lines and read that entire file in at the beginning or read it in chunks. i.e. essentially trying to easily mimic the database and reading aspect rather than generating random seed data as part of the algorithm.
This might at least give a better idea of what needs to truly be optimized in the Ruby code to make it as efficient as possible.
If is still too slow (which could happen - Ruby is certainly not known for its speed) than perhaps just setting up a node process who purpose is to handle it would be the way to go.
Hope this helps