nested loop in show at controller in Ruby optimization - ruby-on-rails

#release = Release.find(params[:id])
#release_cycles=#release.cycles
#release_cycles=Cycle.find_by_sql("select * from cycles where release_id=#{params[:id]}")
current_page=params[:page]?Integer(params[:page]):1
#release_cycles = #release_cycles.paginate(:page=>params[:page],:per_page=>5)
release_ics=#release.ics
puts "params[releases==]==#{params[:releases]}"
releases=params[:releases].to_i
release1=(releases>0)?Release.find(params[:releases]):nil
puts "release1==#{release1}"
#non_ics=(release1!=nil)?(release1.ics):Ic.active
#non_members=[]
#non_ics.each do |non_ic|
check=1
release_ics.each do |release_ic|
if non_ic==release_ic
check=0
puts "inside ics comparison if"
end
end
if check==1
puts "inside if ! in release_only"
#non_members << non_ic
puts "#ics==#{#non_members}"
end
end
...
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #release }
end
end
The commented block of code at the end is eating up runtime like crazy (takes about 20-30 seconds to load) I think I have an idea on how to optimize this but I would like a third person thought on how to optimize the code to make it go faster

Your entire top section of the code can be replaced by 4 lines of code:
#release = Release.find(params[:id])
#release_cycles = #release.cycles.paginate(:page=> params[:page].presence || 1,
:per_page=>5)
#non_ics= params[:releases].present? ? Release.find(params[:releases]).ics :
Ic.active
#non_members = #non_ics - #release.ics
Apart from code that can be improved you are loading all the releases in to memory and paginating the result set in ruby memory space. Which can slow your process down if you have a large number of cycles for each release.
I calculated the intersection between the two arrays in the last line using Ruby. If the array size is big I would use SQL for that.

Related

Catch Exceptions Application Wide

Is there a way of overriding default Exception handling (default rescue), so that I can write custom logic there, for example sending stacktrace to our Slack channel.
Basically I want to make something what NewRelic does with their gem: https://github.com/newrelic/rpm but more local version of it.
Thanks
The simplest thing you could do is instrument all error raising using a TracePoint:
trace = TracePoint.new(:raise) do |tp|
myLogger.log [tp.lineno, tp.event, tp.raised_exception]
end
trace.enable
Using traces used to cause significant code slowdown. I think the new API in ruby 2.0 reduced the slowdown notably. According to my naive benchmark:
count = 10_000_000
t = Time.now
count.times do |i|
begin
0 / 0
rescue
end
end
puts "trial 1: #{Time.now - t}"
t = Time.now
count.times do |i|
"hi"
begin
0 / 0
rescue
end
end
puts "trial 2: #{Time.now - t}"
trace = TracePoint.new(:raise) do |tp|
"hi"
end
trace.enable
t = Time.now
count.times do |i|
begin
0 / 0
rescue
end
end
puts "trial 3: #{Time.now - t}"
#=>trial 1: 10.110471094
#=>trial 2: 9.971755759
#=>trial 3: 11.608365399
Tracepoint only adds 1 second (or 10%) slowdown in 10,000,000 executions of raise. That being said, TracePoint still isn't considered a "production-worthy technique" because it does add overhead and can be hard to predict (eg there are a lot of obscure exceptions in ruby).
If you're wondering how new relic manages to instrument code without overhead:
...
class_eval <<-EOC
def #{with_method_name}(*args, &block)
perform_action_with_newrelic_trace(#{argument_list.join(',')}) do
#{without_method_name}(*args, &block)
end
end
EOC
...
It uses several hundred lines of meta-programming to capture specific methods, deconstruct them, and redefine them with instrumentation inside. This technique requires a lot of code and (I would assume) extra memory and time at start-up, but has the advantage of no additional overhead once the methods are assigned.
Try something like this in application_controller.rb
rescue_from Exception, with: :rescue500 if Rails.env.production?
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found unless Rails.env.development?
def record_not_found
render json: {code: 404, errors: ["Record not found"]}, status: 404
end
def rescue404
render json: {code: 404, errors: ["No round matches"]}, status: 404
end
def rescue500(ex)
Rails.logger.error("\n\nEXCEPTION: #{ex.inspect}\n")
Rails.logger.info(ex)
render json: {code: 500, errors: [ex.message] }, status: 500
end

XML generation very slow and using lots of memory in Rails 4

I'm generating an XML file to share data with another system. From my troubleshooting, I've found that this process is both slow and consuming lots of memory (getting lots of R14's on Heroku.)
My index method on my Jobs Controller looks like this:
def index
respond_to do |format|
format.xml {#jobs = #user.jobs.includes(job_types: [:job_lines, :job_photos])}
format.json
{
# More code here, this part is not the problem.
}
end
end
My view (index.xml.builder) looks like this (I've removed a bunch of fields to keep the example smaller):
xml.instruct!
xml.jobs do
#jobs.each do |j|
xml.job do
xml.id j.id
xml.job_number j.job_number
xml.registration j.registration
xml.name j.name
xml.job_types do
j.job_types.each do |t|
xml.job_type do
xml.id t.id
xml.job_id t.job_id
xml.type_number t.type_number
xml.description t.description
xml.job_lines do
t.job_lines.each do |l|
xml.job_line do
xml.id l.id
xml.line_number l.line_number
xml.job_type_id l.job_type_id
xml.line_type l.line_type
xml.type_number l.type_number
xml.description l.description
xml.part_number l.part_number
end # job_line node
end # job_lines.each
end # job_lines node
xml.job_photos do
t.job_photos.each do |p|
xml.job_photo do
xml.id p.id
xml.pcid p.pcid
xml.job_type_id p.job_type_id
xml.image_url p.image.url
end # job_line node
end # job_lines.each
end # job_lines node
end # job_type
end # job_types.each
end # job_types node
end # job node
end # #jobs.each
end # jobs node
The generated XML file is not small (it's about 100kB). Running on Heroku, their Scout tool tells me that this process is often taking 4-6 seconds to run. Also, despite only running 1 worker, with 4 threads (in Puma) this part of my code is consuming all my memory. In scout, I can see that it's "Max Allocations" are as high as 10M compared with my next worst method which is only 500k allocations.
Can anyone tell me what I'm doing wrong? Is there a more efficient (in terms of speed and memory usage) way for me to generate XML?
Any help would be appreciated.
EDIT 1
I've tried building the XML manually like this:
joblist.each do |j|
result << " <job>\n"
result << " <id>" << j.id.to_s << "</id>\n"
result << " <job_number>" << j.job_number.to_s << "</job_number>\n"
# Lots more lines removed
end
This has given me some improvements. My largest allocations is now 1.8M. I'm close to Heroku's limit (reached a max of 500MB out of the 512MB limit over 24 hours).
I am still only running 1 Worker with 4 threads.If I can I'd like to get the memory down more so I can run some more Puma Workers and Threads.
EDIT 2
I ended up having to do this in batches (using offset and limit) and send 5 jobs at a time. The memory usage dropped substantially when I did this. Obviously there was more calls to the controller but each was smaller and faster.

Automatically Scheduling Conference

I'm trying to create a Ruby on Rails site that manages conferences. It should fill in time slots without any gaps in between. I've got it to the point where it fill in the the slots. But in most instances it leaves some time slots empty. I'm not able to find the flow in my logic.
app/services/conference_service.rb
class ConferenceService
def initialize(conference, temp_file)
self.first_track = conference.tracks.first
self.second_track = conference.tracks.last
self.file = temp_file
self.talks = []
end
def call
create_talks
set_track(1, 'Lunch')
set_track(2, 'Lunch')
set_track(1, 'Networking Event')
# set_track(2, 'Networking Event')
set_second_track_evening
end
private
def create_talks
file.read.split(/\n/).each do |line|
next if line.blank?
title = line.split(/\d|lightning/).first
length = line.scan(/\d+/).first
length = length.nil? ? 5 : length.to_i
talks << Talk.create(title: title, length: length)
end
end
attr_accessor :first_track, :second_track, :file, :talks
def set_track(track_number, track_portion)
track = track_number == 1 ? first_track : second_track
time = track_portion == 'Lunch' ? Time.zone.now.change(hour: 9) : Time.zone.now.change(hour: 13)
minutes = track_portion == 'Lunch' ? 180 : 240
talks.shuffle!
local_talks = []
n = 0
while local_talks.map(&:length).inject(0, &:+) < minutes
local_talks << talks[n]
n += 1
end
if local_talks.map(&:length).inject(0, &:+) == minutes
local_talks.each do |talk|
talk.start_time = time
track.talks << talk
time = time.advance(minutes: talk.length)
end
track.talks << Talk.create(title: track_portion, start_time: time, length: 60)
track.save
(0..local_talks.count - 1).each do |i|
talks.delete_at(i)
end
else
set_track(track_number, track_portion)
end
end
def set_second_track_evening
time = Time.zone.now.change(hour: 13)
talks.each do |talk|
talk.start_time = time
time = time.advance(minutes: talk.length)
end
second_track.talks << talks
second_track.talks << Talk.create(title: 'Networking Event', start_time: time.change(hour: 17), length: 60)
end
end
app/controllers/conference_controller.rb
def create
#conference = Conference.new(conference_params)
build_tracks
conference_service = ConferenceService.new(#conference, input_file)
conference_service.call
respond_to do |format|
if #conference.save
format.html { redirect_to #conference, notice: 'Conference was successfully created.' }
format.json { render :show, status: :created, location: #conference }
else
format.html { render :new }
format.json { render json: #conference.errors, status: :unprocessable_entity }
end
end
end
def input_file
params['conference']['input_file']
end
input file
Writing Fast Tests Against Enterprise Rails 60min
Overdoing it in Python 45min
Lua for the Masses 30min
Ruby Errors from Mismatched Gem Versions 45min
Common Ruby Errors 45min
Rails for Python Developers lightning
Communicating Over Distance 60min
Accounting-Driven Development 45min
Woah 30min
Sit Down and Write 30min
Pair Programming vs Noise 45min
Rails Magic 60min
Ruby on Rails: Why We Should Move On 60min
Clojure Ate Scala (on my project) 45min
Programming in the Boondocks of Seattle 30min
Ruby vs. Clojure for Back-End Development 30min
Ruby on Rails Legacy App Maintenance 60min
A World Without HackerNews 30min
User Interface CSS in Rails Apps 30min
error when calling set_track(2, 'Networking Event')
undefined method `length' for nil:NilClass #line 42
Recommend you do a few things before worrying about the algorithm:
Separate concerns / Single Responsibility. The code that parses the file should be independent from the code that runs the business logic, which should be independent from the code that saves to your database. Separating these things may seem unnecessary for simple logic (and may be), but is necessary as your app complexity grows.
Write tests. As you refactor your code, you're going to want to ensure it still works. Bonus: Writing code that you can test forces you to create interfaces that you can understand, which can make the code easier to understand!
Come up with a design first. Reading this code I have no idea what the intention of the sections are. One of my favorite ways to do this is to use Class, Responsibilities, Collaborators post cards (see https://en.wikipedia.org/wiki/Class-responsibility-collaboration_card and http://agilemodeling.com/artifacts/crcModel.htm).
It seems like you could break this code down into:
Parse input file into generic 'Talk' objects that have a length (in minutes) and a name. I would not have these be DB backed. If it's the same concept as an ActiveRecord model, we often name this a TalkDouble (or similar). I'd also recommend just using CSV here rather than your own custom (and hard to parse) format.
Schedule talk objects into tracks. It seems like you're trying to randomize the talks across two tracks, with some built-in lunch breaks (?). Whatever the desired behavior, this also doesn't need to use anything but plain old ruby objects. I've found it best to have the logic be stateless/idempotent and return a new object each time it's run as the result.
For example:
class TalkScheduler
def schedule(talks, number_of_tracks: 2)
# Logic goes here, returns an array of `Tracks`
# each with a set of talks.
tracks = build_tracks(number_of_tracks)
talks.each do |talk|
tracks.sample.add_talk(talk)
end
tracks
end
def build_tracks(number)
(0..number).times.map do { Track.new }
end
end
However, if you're looking for an algorithm that chooses "best fit" of available talks into open spaces, you're essentially trying to solve the Knapsack problem (https://en.wikipedia.org/wiki/Knapsack_problem). It may not become combinatorially hard due to the limited number of talk lengths (e.g. only 30, 45 and 60) but realize that you're slipping into challenging territory.
I'd also question the value to anyone of the ability to create conference with a random order of talks vs. just being able to organize them by hand.
In any case, you could handle solving the problem of determining a (random?) selection of talks in a given time-space with something like the following:
class Schedule
SLOT_LENGTH = 15
attr_accessor :start, :length, :talks
def initialize(start:, length:)
#start = start
#length = length
#slots = length / SLOT_LENGTH
#talks = []
end
def add_talk(talk)
talks.push(talk)
end
def slots_remaining
slots - talks.map(&:length).sum / SLOT_LENGTH
end
def can_fit?(talk)
talk.length / SLOT_LENGTH <= slots_remaining
end
end
class TalkScheduler
def schedule(talks, schedules)
unscheduled_talks = talks.dup.shuffle # Always dup, even if you don't shuffle
schedules.each do |schedule|
while(talks.any?)
index = unscheduled_talks.index{|t| schedule.can_fit?(t) }
break unless index
talk = unscheduled_talks.delete_at(index)
schedule.add_talk(talk)
end
end
end
end
I'd think a bit more about to model lunches, networking breaks, etc. before deciding to model them as talks or as something else, but using this type of pattern (simple ruby objects that store data being manipulated by NounVerber classes that contain the complex business logic) has been very helpful to me for simplifying handling complex workflows like what you're doing here.
Good luck!

Benchmarking controller + view together, many times in one go

I am learning how to benchmark two implementations in the controller/view. They are doing th e same thing, but one is done in view and another in controller. The code is shown below. My questions are:
is it possible to measure the taken for the same action to render 100 times in one go?
is my current benchmarking correctly measuring the combination of view + controller times?
is there any better way to do this?
```
def sort_in_view
self.class.benchmark("$sort in view") do
#regions = Region.all
respond_to do |format|
format.html
end
end
end
def sort_in_controller
self.class.benchmark("$sort in controller") do
#regions = {}
Region.all.each do |r|
#regions[r] = r.countries.order_by_name
end
respond_to do |format|
format.html
end
end
end
In order to run each case many times to get a more accurate average, I used Apache Benchmark at the end.
ab -c 1 -n 100 http://example.com/regions
This will run the request 100 times (with concurrency of 1), and give you a detailed summary of the mean and percentiles. I benchmark against my local machine, and it saves time since no browser rendering is required.
see benchmaek results,just see your Rails log

Explain Iterator Syntax on Ruby on Rails

I started learning Ruby on Rails and found myself confounded by the syntax, so I had to read about somet of the Ruby syntax. I learned the syntax from http://www.cs.auckland.ac.nz/references/ruby/doc_bundle/Manual/man-1.4/syntax.html:
method_call do [`|' expr...`|'] expr...end
They call it an Iterator. I understand an iterator runs through a loop, but I don't understand how exactly I'm supposed to read this or what's going on in in this syntax. I see it all the time in RoR screencasts and the words make sense, but I actually have no idea what's going on. Could anyone explain this to me?
edit: example
respond_to do |format|
format.json
format.xml { render :xml => #posts }
end
Methods can take a construct called "Blocks". These are anonymous methods that get passed into the method.
Another syntax for this is:
method_call { |var| do_something(var) }
Basically, you are saying that for each item in an iteration, name it "var" and do something with that item. The method simply calls your block that you passed in as it "yields" items to it.
Does this help?
edit: In your example, you they are using the iterator pattern in a funny way... probably only passing one format object into your block, so you can then tell it which formats to handle, and what to do when you see it.
In other words, they are using the pattern to create a DSL of sorts that lets you configure what you respond to.
In the case of iterators, think of them like an interface in Java: you can do a for-loop in Ruby, but all the objects that you might want to iterate over (should) implement the 'each' method which takes a block (i.e. a closure, an anonymous function).
Blocks are used all over the place in Ruby. Imagine you have this array:
[1, 2, 3, 4, 5, 6].each do |i| puts i.to_s end
Here, you are creating the array and then you are calling the 'each' method on it. You pass the block to it. You could separate this out, like this:
arr = [1, 2, 3, 4, 5, 6]
string_printer = lambda do |i| puts i.to_s end
arr.each(&string_printer)
This kind of interface is implemented in other things: the Hash collection lets you iterate over the key-value pairs:
{:name => "Tom", :gender => :male}.each do |key, value| puts key end
The do..end can be replaced with braces, like this:
[1, 2, 3, 4, 5, 6].each {|i| puts i.to_s }
This kind of iteration is made possible because of the functional-programming that Ruby employs: if you are creating a class that needs to iterate over something, you can also implement the each method. Consider:
class AddressBook
attr_accessor :addresses
def each(&block)
#addresses.each {|i| yield i }
end
end
All sorts of classes implement interesting functionality through this block pattern: look at String's each_line and each_byte method, for instance.
method_call do [`|' expr...`|'] expr...end
Is not limited to iteration functions.
In ruby, any method can take a block as an argument. The block can then be called by the method. In the case of an iterator, the method looks something like this:
def iter
for i in [:x,:y,:z]
yield i
end
end
If you call iter with a block, it will loop over [:x, :y, :z] and yield each of them to the block, which can then do whatever you want. e.g. to print them out:
iter { |z| puts z }
You can also use this to hide init and cleanup steps, like opening and closing files. e.g. File.open. File.open, if it were implemented in pure ruby(it's in C for performance) would do something like this.
def File.open filename, opts
f = File.new filename, opts
yield f
f.close
end
Which is why you can use
File.open 'foobar', 'w' do |f|
f.write 'awesome'
end
respond_to is similar. It works something like this:( check out the real implementation here)
def respond_to
responder = Responder.new(self)
block.call(responder)
responder.respond
end
It creates a responder object that has methods like html that take a block and passes it to you. This turns out to be really handy, because it lets you do things like:
def action
#foo = Foo.new params[:foo]
respond_to do |format|
if #foo.save
format.html { redirect_to foo_path #foo }
format.xml { render :xml => #foo.to_xml }
else
flash[:error] = "Foo could not be saved!"
format.html { render :new }
format.xml { render :xml => {:errors => #foo.errors }.to_xml}
end
end
end
See how I change the behavior dependent on save inside the block? Doing this would be much more annoying without it.
<function> do |<temp variable>|
<code to operate on temp variable>
end
This creates a temporary anonymous function which accepts an item into a temporary variable, and then lets things operate on that item. The anonymous function is passed in to the original <function> specified to operate on the items yielded by that function.
What you see there is a block of code, the syntax is a bit awkward when you first see it.
So, basically, with iterators your have a "thing" that may be repeated, and it receives a block to know what to do.
For instance the Range class has a method called "each" which receives the block of code to execute on each element in the range.
Let's say you want to print it:
range = 1..10 #range literal
range.each {|i|
puts i
}
The code: {|i| puts i} is a block that says what to do when this range iterates over each one of its elements. The alternate syntax is the one you posted:
range.each do |i|
puts i
end
These blocks are used with iterators, but they are not limited to "iteration" code, you can use them in other scenarios, for instance:
class Person
def initialize( with_name )
#name = with_name
end
# executes a block
def greet
yield #name #passes private attribute name to the block
end
end
p = Person.new "Oscar"
p.greet { |n|
puts "Name length = #{n.length}"
puts "Hello, #{n}"
}
Prints:
Name length = 5
Hello, Oscar
So, instead of having a greet method with a fixed behavior, using block let the developer specify what to do, which is very helpful with iterators, but as you have just witness not the only place. In your case, that block is letting you specify what to do in the respond_to method.
The documentation you are reading is ancient -- practically prehistoric. If it were possible for web pages to gather dust, that one would have a thick layer.
Try the reference material at the ruby-lang website. Also, the Programming Ruby (pickaxe) book is an essential reference.
I think you could call it iterator, because often, the block function is called more than once. As in:
5.times do |i|
puts "#{i} "
end
"Behind the scenes", the following steps are made:
The method times of the object instance 5 is called, passing the code puts "#{i} " in a Proc object instance.
Inside the times method, this code is called inside a loop, passing the current index as a parameter. That's what times could look like (it's in C, actually):
class Fixnum
def times_2(&block) # Specifying &block as a parameter is optional
return self unless block_given?
i = 0
while(i < self) do
yield i # Here the proc instance "block" is called
i += 1
end
return self
end
end
Note that the scope (i.e. local variables etc.) is copied into the block function:
x = ' '
5.times do { |i| puts "#{i}" + x }

Resources