Skip to content

Commit

Permalink
Merge pull request #79 from BallAerospace/improve_memory_utilization
Browse files Browse the repository at this point in the history
Fix memory allocation problems #78
  • Loading branch information
jmthomas committed Mar 12, 2015
2 parents aae53a5 + 2cf1957 commit fc3772d
Show file tree
Hide file tree
Showing 230 changed files with 5,350 additions and 161 deletions.
14 changes: 7 additions & 7 deletions lib/cosmos/core_ext/time.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,27 +78,27 @@ def self.format_seconds(seconds)
dd, hh = hh.divmod(24)
if dd != 0
if dd == 1
result += "%d day, " % dd
result << "%d day, " % dd
else
result += "%d days, " % dd
result << "%d days, " % dd
end
end
if hh != 0
if hh == 1
result += "%d hour, " % hh
result << "%d hour, " % hh
else
result += "%d hours, " % hh
result << "%d hours, " % hh
end
end
if mm != 0
if mm == 1
result += "%d minute, " % mm
result << "%d minute, " % mm
else
result += "%d minutes, " % mm
result << "%d minutes, " % mm
end
end
if ss > 0
result += "%.2f seconds" % ss
result << "%.2f seconds" % ss
else
result = result[0..-3]
end
Expand Down
4 changes: 2 additions & 2 deletions lib/cosmos/gui/dialogs/about_dialog.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ def initialize (parent, about_string)
configurable_about_text = File.read(filename)
configurable_about_text.gsub!("\r", '') unless Kernel.is_windows?
if Kernel.is_windows?
configurable_about_text += "\n" + "Main Application x:#{parent.x} y:#{parent.y} width:#{parent.frameGeometry.width + 16} height:#{parent.frameGeometry.height + 38}\n\n" + ABOUT_COSMOS
configurable_about_text << "\n" + "Main Application x:#{parent.x} y:#{parent.y} width:#{parent.frameGeometry.width + 16} height:#{parent.frameGeometry.height + 38}\n\n" + ABOUT_COSMOS
else
configurable_about_text += "\n" + "Main Application x:#{parent.x} y:#{parent.y} width:#{parent.frameGeometry.width} height:#{parent.frameGeometry.height}\n\n" + ABOUT_COSMOS end
configurable_about_text << "\n" + "Main Application x:#{parent.x} y:#{parent.y} width:#{parent.frameGeometry.width} height:#{parent.frameGeometry.height}\n\n" + ABOUT_COSMOS end

# Set the application about text
about = Qt::Label.new(about_string + "\n\n" + configurable_about_text)
Expand Down
4 changes: 2 additions & 2 deletions lib/cosmos/gui/dialogs/exception_dialog.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ def initialize(parent, exception, title = 'COSMOS Exception', exit_afterwards =
rescue
end
text = "The following error occurred:<br/>#{message}"
text += "<br/><br/>Please contact your local COSMOS expert.<br/><br/>This error has been logged:<br/>#{log_file}<br/><br/> <a href='mailto:[email protected];[email protected]?subject=COSMOS exception&body=#{file_contents}'>Click here</a> to email this log to the COSMOS developers." if log_file
text << "<br/><br/>Please contact your local COSMOS expert.<br/><br/>This error has been logged:<br/>#{log_file}<br/><br/> <a href='mailto:[email protected];[email protected]?subject=COSMOS exception&body=#{file_contents}'>Click here</a> to email this log to the COSMOS developers." if log_file
end
text += "<br/><br/>NOTE!: The application will exit once you accept or dismiss this dialog!" if exit_afterwards
text << "<br/><br/>NOTE!: The application will exit once you accept or dismiss this dialog!" if exit_afterwards
msg.setText(text)
if log_file
open_button = Qt::PushButton.new("Open Exception Log in Text Editor")
Expand Down
2 changes: 1 addition & 1 deletion lib/cosmos/gui/dialogs/tlm_details_dialog.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def update_limits_details(limits_settings, limits_set)
if limits_settings[0]
label_text = "RL/#{limits_settings[0][0]} YL/#{limits_settings[0][1]} YH/#{limits_settings[0][2]} RH/#{limits_settings[0][3]}"
if limits_settings[0][4] and limits_settings[0][5]
label_text += " GL/#{limits_settings[0][4]} GH/#{limits_settings[0][5]}"
label_text << " GL/#{limits_settings[0][4]} GH/#{limits_settings[0][5]}"
end
if @limits_labels[limits_set]
@limits_labels[limits_set].text = label_text
Expand Down
4 changes: 2 additions & 2 deletions lib/cosmos/gui/line_graph/line_graph_drawing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ def draw_legend(dc)
right_text_x = text_x + (legend_width / 2)
left_text_y = text_y
right_text_y = text_y
@lines.legend.reverse.each do |legend_text, color, axis|
@lines.legend.reverse_each do |legend_text, color, axis|
if axis == :LEFT
dc.addSimpleTextAt(legend_text, left_text_x, left_text_y, color)
left_text_y -= metrics.height
Expand All @@ -375,7 +375,7 @@ def draw_legend(dc)
text_y = right_text_y
end
else
@lines.legend.reverse.each do |legend_text, color, axis|
@lines.legend.reverse_each do |legend_text, color, axis|
dc.addSimpleTextAt(legend_text, text_x, text_y, color)
text_y -= metrics.height
end
Expand Down
44 changes: 22 additions & 22 deletions lib/cosmos/gui/qt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -428,54 +428,43 @@ def text=(value)
end

class Qt::PlainTextEdit
@@color_cache = {}

def add_formatted_text(text, color = nil)
if text =~ /[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F-\xFF]/
text.chomp!
text = text.inspect.remove_quotes
text << "\n"
end
if text =~ /<G>/ or color == Cosmos::GREEN
text.gsub!('<G>', '')
text.gsub!(/<G>/, '')
addText(text, Cosmos::GREEN)
elsif text =~ /<Y>/ or color == Cosmos::YELLOW
text.gsub!('<Y>', '')
text.gsub!(/<Y>/, '')
addText(text, Cosmos::YELLOW)
elsif text =~ /<R>/ or color == Cosmos::RED
text.gsub!('<R>', '')
text.gsub!(/<R>/, '')
addText(text, Cosmos::RED)
elsif text =~ /<B>/ or color == Cosmos::BLUE
text.gsub!('<B>', '')
text.gsub!(/<B>/, '')
addText(text, Cosmos::BLUE)
else
addText(text) # default is Cosmos::BLACK
end
end

def addText(text, color = Cosmos::BLACK)
@current_text = "" if !defined? @current_text or @current_text.nil?
text = text.gsub("&", "&amp;")
text.gsub!("\n", '')
text.gsub!(' ', '&nbsp;')
text.gsub!(">", "&gt;")
text.gsub!("<", "&lt;")
rgb_color = "#%02X%02X%02X" % [color.red, color.green, color.blue]
@current_text +="<font color=\"#{rgb_color}\">#{text}</font><br/>"
@current_text ||= ''
@current_text << escape_text(text.chomp, color) << '<br/>'.freeze
end

def flush
appendHtml(@current_text)
@current_text = nil
@current_text.clear
end

def appendText(text, color = Cosmos::BLACK)
text = text.chomp
text.gsub!(/\n/, '<br/>') # replace newlines with html breaks
text.gsub!("&", "&amp;")
text.gsub!(' ', '&nbsp;')
text.gsub!(">", "&gt;")
text.gsub!("<", "&lt;")
rgb_color = "#%02X%02X%02X" % [color.red, color.green, color.blue]
appendHtml("<font color=\"#{rgb_color}\">#{text}</font>")
appendHtml(escape_text(text.chomp, color))
end

# Return the selected lines. If a partial line is selected the entire line will be returned.
Expand Down Expand Up @@ -522,6 +511,17 @@ def selection_end_line
cursor.setPosition(textCursor.selectionEnd)
cursor.blockNumber
end

private

def escape_text(text, color)
# You might think gsub! would use less memory but benchmarking proves gsub
# with a regular express argument is the fastest and uses the least memory.
# However, this is still an expensive operation due to how many times it is called.
text = text.gsub(/&/,'&amp;'.freeze).gsub(/\n/,'<br/>'.freeze).gsub(/\s/, '&nbsp;'.freeze).gsub(/>/,'&gt;'.freeze).gsub(/</,'&lt;'.freeze)
@@color_cache[color] ||= "#%02X%02X%02X" % [color.red, color.green, color.blue]
"<font color=\"#{@@color_cache[color]}\">#{text}</font>"
end
end

class Qt::TextEdit
Expand All @@ -533,7 +533,7 @@ def setColors(foreground, background)
class Qt::ComboBox
# Helper method to remove all items from a ComboBox
def clearItems
(0...count).to_a.reverse.each do |index|
(0...count).to_a.reverse_each do |index|
removeItem(index)
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/cosmos/io/json_drb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def graceful_kill
def start_service(hostname = nil, port = nil, object = nil)
if hostname and port and object
@object = object
hostname = '127.0.0.1' if (hostname.to_s.upcase == 'LOCALHOST')
hostname = '127.0.0.1'.freeze if (hostname.to_s.upcase == 'LOCALHOST'.freeze)

# Create a socket to accept connections from clients
begin
Expand Down Expand Up @@ -171,7 +171,7 @@ def average_request_time
def self.receive_message(socket, data)
self.get_at_least_x_bytes_of_data(socket, data, 4)
if data.length >= 4
length = data[0..3].unpack('N')[0]
length = data[0..3].unpack('N'.freeze)[0]
data.replace(data[4..-1])
else
return nil
Expand Down Expand Up @@ -200,7 +200,7 @@ def self.get_at_least_x_bytes_of_data(socket, current_data, required_num_bytes)
return
end
current_data << data
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
rescue IO::WaitReadable
IO.fast_select([socket], nil, nil, nil)
retry
end
Expand All @@ -215,7 +215,7 @@ def self.send_data(socket, data, send_timeout = 10.0)
num_bytes_to_send = data.length + 4
total_bytes_sent = 0
bytes_sent = 0
data_to_send = [data.length].pack('N') << data.clone
data_to_send = [data.length].pack('N'.freeze) << data.clone

loop do
begin
Expand Down
42 changes: 21 additions & 21 deletions lib/cosmos/io/json_rpc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,28 +183,28 @@ class JsonRpcRequest < JsonRpc
# @param id [Integer] The identifier which will be matched to the response
def initialize(method_name, method_params, id)
super()
@hash['jsonrpc'] = "2.0"
@hash['method'] = method_name.to_s
@hash['jsonrpc'.freeze] = "2.0".freeze
@hash['method'.freeze] = method_name.to_s
if method_params and method_params.length != 0
@hash['params'] = method_params
@hash['params'.freeze] = method_params
end
@hash['id'] = id.to_i
@hash['id'.freeze] = id.to_i
end

# @return [String] The method to call
def method
@hash['method']
@hash['method'.freeze]
end

# @return [Array<String>] Array of strings which represent the
# parameters to send to the method
def params
@hash['params'] || []
@hash['params'.freeze] || []
end

# @return [Integer] The request identifier
def id
@hash['id']
@hash['id'.freeze]
end

# Creates a JsonRpcRequest object from a JSON encoded String. The version
Expand All @@ -216,7 +216,7 @@ def self.from_json(request_data)
begin
hash = JSON.parse(request_data, :allow_nan => true, :create_additions => true)
# Verify the jsonrpc version is correct and there is a method and id
raise unless (hash['jsonrpc'] == "2.0" && hash['method'] && hash['id'])
raise unless (hash['jsonrpc'.freeze] == "2.0".freeze && hash['method'.freeze] && hash['id'.freeze])
self.from_hash(hash)
rescue
raise "Invalid JSON-RPC 2.0 Request"
Expand All @@ -229,7 +229,7 @@ def self.from_json(request_data)
# and id
# @return [JsonRpcRequest]
def self.from_hash(hash)
self.new(hash['method'], hash['params'], hash['id'])
self.new(hash['method'.freeze], hash['params'.freeze], hash['id'.freeze])
end
end

Expand All @@ -239,8 +239,8 @@ class JsonRpcResponse < JsonRpc
# @param id [Integer] The identifier which will be matched to the request
def initialize(id)
super()
@hash['jsonrpc'] = "2.0"
@hash['id'] = id
@hash['jsonrpc'.freeze] = "2.0".freeze
@hash['id'.freeze] = id
end

# Creates a JsonRpcResponse object from a JSON encoded String. The version
Expand All @@ -258,13 +258,13 @@ def self.from_json(response_data)
end

# Verify the jsonrpc version is correct and there is an ID
raise msg unless hash['jsonrpc'] == "2.0" and hash.key?('id')
raise msg unless hash['jsonrpc'.freeze] == "2.0".freeze and hash.key?('id'.freeze)
# If there is a result this is probably a good response
if hash.key?('result')
if hash.key?('result'.freeze)
# Can't have an error key in a good response
raise msg if hash.key?('error')
raise msg if hash.key?('error'.freeze)
JsonRpcSuccessResponse.from_hash(hash)
elsif hash.key?('error')
elsif hash.key?('error'.freeze)
# There was an error key so create an error response
JsonRpcErrorResponse.from_hash(hash)
else
Expand All @@ -280,20 +280,20 @@ class JsonRpcSuccessResponse < JsonRpcResponse
# @param id [Integer] The identifier which will be matched to the request
def initialize(result, id)
super(id)
@hash['result'] = result
@hash['result'.freeze] = result
end

# @return [Object] The result of the method request
def result
@hash['result']
@hash['result'.freeze]
end

# Creates a JsonRpcSuccessResponse object from a Hash
#
# @param hash [Hash] Hash containing the following keys: result and id
# @return [JsonRpcSuccessResponse]
def self.from_hash(hash)
self.new(hash['result'], hash['id'])
self.new(hash['result'.freeze], hash['id'.freeze])
end
end

Expand All @@ -304,20 +304,20 @@ class JsonRpcErrorResponse < JsonRpcResponse
# @param id [Integer] The identifier which will be matched to the request
def initialize(error, id)
super(id)
@hash['error'] = error
@hash['error'.freeze] = error
end

# @return [JsonRpcError] The error object
def error
@hash['error']
@hash['error'.freeze]
end

# Creates a JsonRpcErrorResponse object from a Hash
#
# @param hash [Hash] Hash containing the following keys: error and id
# @return [JsonRpcErrorResponse]
def self.from_hash(hash)
self.new(JsonRpcError.from_hash(hash['error']), hash['id'])
self.new(JsonRpcError.from_hash(hash['error'.freeze]), hash['id'.freeze])
end
end

Expand Down
Loading

0 comments on commit fc3772d

Please sign in to comment.