Google Interview Question
Senior Software Development EngineersTeam: Performance Optimization Team
Country: United States
Interview Type: In-Person
Based on @ChrisK s comment, I have heavily commented the code. @ChrisK, start using ZoomBA. :-)
/* Make times calls to print stats on a static url
Making it heavily documented so that ChrisK
can read ZoomBA. It is trivial, once you master
what -> , :: , $ are.
-> is "as" that is a mapper function
:: is "where" that is a predicate, a condition
$ is the iteration variable, holding
$.o -> object of iteration , the item
$.i -> the index of the current iteration
$.c -> the context, the iterable on which iteration is happening
$.p -> partial, the result of the iteration, as of now
*/
def analyze ( url, times=10) {
percentiles = [ 0.99, 0.95, 0.9 , 0.5, 0.1 ]
// an inner function
def timing( url ){
// gets the pair, timing in sec, output of the call
// using clock statetement
// which has the read function to readf from the url
#(t,o) = #clock { read ( url ) }
t // return value are implicit like scala, no point saying return
// side effect, there is really no truly void function in ZoomBA
}
def parallelize( url , times ){
// create a list of *times* threads
// each thread has a body of function call timing()
// zoomba threads have a field :value, which stores the thread functions return value
// this is massive improvement from Java, see similar code and the pain below
threads = list([0:times] ) -> { thread() -> { timing( url ) } }
// polls num tries, poll-interval, until condition is true
// returns true if condition was true, else returns false
// :: (such that) is a short form of where clase in zoomba
// the code waits till no alive thread
// shorthand of java function isXxx() -> xxx in zoomba
// making it way more succint
// could easily be done using a .join() but, why care?
poll(300,50) :: { !exists( threads ) :: { $.o.alive } }
// extracting the return value of the threads into another list
// -> is the 'as' symbol
// it reads create a list from ( threads ) as ( mapping ) thread.value as the item
// $ is the iteration construct, more like *this* for a loop.
// $.o stores the iteration object for the loop, this this case, a thread object
list( threads ) -> { $.o.value }
}
def stats( data ){
// sum
mean = sum(data) / size(data)
// sum over item - mean whole squared, right?
variance = sum( data ) -> { ($.o - mean) ** 2 }
sd = variance ** 0.5
printf( 'mean: %s\n', mean )
printf( 'sd: %s\n', sd )
// now percentile calculations
// sorta --> sort ascending the data values
sorta(data)
// another iteration - for() would be same
fold ( percentiles ) ->{
printf( '%.2fp: %s\n', $.o , data[floor( size(data) * $.o )] )
}
}
println('url -> ' + url )
println('num of times -> ' + times )
println('All in secconds.')
data = parallelize( url, times )
stats(data)
}
There are certain edge cases to this code. Why to check for the entire response. Why not just check the response code of '200'. This might save some time. As this is "Performance Team", I bet the requirements would be high enough to provide production quality code. Though the question is simple I agree, but the answer would require handling edge cases, such as checking if the remote is reachable, checking the response code for 200 and others
Here is something in Java.
Please get over Java. It shows you how lame as a language it really is.
- NoOne June 10, 2017