我正在尝试在 Swift 中构建一个数据结构,将一个 Integer 映射到一个对象数组(一个以 int 作为键和数组作为值的字典)。这些对象非常小,它们只是包装了一个 UIColor 和一个 Int。我有两个实现,一个使用 Swift 数组作为 Dictionary 的值类型,而另一个使用 NSMutableArray 作为值类型。我的 Objective-C 代码执行得非常快,但我的 Swift 代码运行得非常慢。理想情况下,我不想使用 NSMutableArray,而是希望将其保留为 Swift 数组。这样做的原因是我正在编写算法和性能问题,我注意到 objC_msgSend 有一些开销。谁能帮我优化我的 Swift 代码?我是在做错什么,还是这只是将数组快速处理为值类型的副产品?如果是,我想了解为什么值类型在这种情况下执行得如此缓慢,我的选择是什么,以及这种情况如何才能向前扩展?下面我发布了一个代码片段和由此产生的基准:
Swift 数组代码:
let numColors = colorCount(filter: filter, colorInfoCount: colorInfo.count)
var colorCountsArray: [Int] = [Int]()
var countToColorMap: [Int:[CountedColor]] = [Int:[CountedColor]](minimumCapacity: capacity)
var topColors = [CountedColor]()
var startTime = CACurrentMediaTime()
for (color, colorCount) in colorInfo {
colorCountsArray.append(colorCount)
if countToColorMap[colorCount] != nil {
countToColorMap[colorCount]?.append(CountedColor(color: color, colorCount: colorCount))
} else {
countToColorMap[colorCount] = [CountedColor(color: color, colorCount: colorCount)]
}
}
var endTime = CACurrentMediaTime()
print("Time after mapping: \(endTime - startTime)")
快速性能:
Time after mapping: 45.0881789259997
NSMutableArray 代码:
let numColors = colorCount(filter: filter, colorInfoCount: colorInfo.count)
var colorCountsArray: [Int] = [Int]()
var countToColorMap: [Int:NSMutableArray] = [Int:NSMutableArray](minimumCapacity: capacity)
var topColors = [CountedColor]()
var startTime = CACurrentMediaTime()
for (color, colorCount) in colorInfo {
colorCountsArray.append(colorCount)
if countToColorMap[colorCount] != nil {
countToColorMap[colorCount]?.add(CountedColor(color: color, colorCount: colorCount))
} else {
countToColorMap[colorCount] = NSMutableArray(object: CountedColor(color: color, colorCount: colorCount))
}
}
var endTime = CACurrentMediaTime()
print("Time after mapping: \(endTime - startTime)")
NSMutableArray 性能:
Time after mapping: 0.367132211999888
colorInfo 对象是一个将 UIColor 对象映射到表示计数的整数值的字典。代码基本上反向映射它,将整数映射到 UIColor 数组(它是一个数组,因为多个颜色可以具有相同的计数)。 colorInfo 内部有 60,000 个 UIColor、Int 键值对。
最佳答案
写时复制是一件棘手的事情,您需要仔细考虑有多少东西共享您要修改的结构。罪魁祸首就在这里。
countToColorMap[colorCount]?.append(CountedColor(color: color as! UIColor, colorCount: colorCount))
这会生成一个临时值,该值会被修改并放回字典中。由于两个“事物”正在查看相同的底层数据结构(字典和 append),它会强制执行写时复制。
解决此问题的秘诀是确保在修改时只有一个副本。如何?把它从字典里拿出来。替换为:
if countToColorMap[colorCount] != nil {
countToColorMap[colorCount]?.append(CountedColor(color: color as! UIColor, colorCount: colorCount))
} else {
countToColorMap[colorCount] = [CountedColor(color: color as! UIColor, colorCount: colorCount)]
}
其运行时间为:
Elapsed Time: 74.2517465990022
53217
用这个:
var countForColor = countToColorMap.removeValue(forKey: colorCount) ?? []
countForColor.append(CountedColor(color: color as! UIColor, colorCount: colorCount))
countToColorMap[colorCount] = countForColor
其运行时间为:
Elapsed Time: 0.370953808000195
53217
关于swift - Swift 中以可变数组为值的字典执行速度很慢?如何优化或正确构建?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41079687/
我想用sunspot重现以下原始solr查询q=exact_term_text:fooORterm_textv:foo*ORalternate_text:bar*但我无法通过标准的太阳黑子界面理解这是否可能以及如何实现,因为看起来:fulltext方法似乎不接受多个文本/搜索字段参数我不知道将什么参数作为第一个参数传递给fulltext,就好像我通过了"foo"或"bar"结果不匹配如果我传递一个空参数,我得到一个q=*:*范围过滤器(例如with(:term).starting_with('foo*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使
有没有一种简单的方法来测试一个对象是不可变的(数字,零)还是不可变的(数组,哈希,对象)?换句话说,是否可以通过其他代码的副作用更改它?动机:我想创建一个版本化的值存储,但有些数据是数组。一些数组将存储自定义对象,我可以通过存储“in”属性并搜索它来反转关系。但我也希望能够存储符号数组、其他数组等。 最佳答案 我发现了一个低效的方法:classObjectdefprimitive?beginself.dupfalserescueTypeErrortrueendendend 关于ruby-
如何获取外部命令的输出并从中提取值?我有这样的东西:stdin,stdout,stderr,wait_thr=Open3.popen3("#{path}/foobar",configfile)if/exit0/=~wait_thr.value.to_srunlog.puts("Foobarexitednormally.\n")puts"Testcompleted."someoutputvalue=stdout.read("TX.*\s+(\d+)\s+")puts"Outputvalue:"+someoutputvalueend我没有在标准输出上使用正确的方法,因为Ruby告诉我它不能
我有一个Highstock图表(带有标记和阴影的线条),并且想以编程方式显示一个highstock工具提示,例如,当我选择某个表上的一行(包含图表数据)我想显示相应的highstock工具提示。这可能吗? 最佳答案 股票图表thissolution不起作用:在thisexample你必须更换这个:chart.tooltip.refresh(chart.series[0].data[i]);为此:chart.tooltip.refresh([chart.series[0].points[i]]);解决方案可用here.
当我写这篇文章时,我以为我是Ruby巨人:#havingthishashhash={'Portugal'=>1,'France'=>2,'USA'=>3}#country_idcomesfrominputcountry_name=(hash.select{|k,v|v==country_id.to_i}.first||[]).first它确实正确地提取了国家名称,如果找不到国家也不会失败。我对此非常满意。但是我的导师说它可以/应该在可读性、长度和性能方面进行优化!还有什么比这更清晰/更快的呢?请指教 最佳答案 嗯,看来你的导师是对的
为什么下面的代码会报错?['hello','stack','overflow'].inject{|memo,s|memo+s.length}TypeError:can'tconvertFixnumintoStringfrom(irb):2:in`+'from(irb):2:in`blockinirb_binding'from(irb):2:in`each'from(irb):2:in`inject'from(irb):2如果传递了初始值,它就可以正常工作:['hello','stack','overflow'].inject(0){|memo,s|memo+s.length}=>18
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。在我在网上找到的每个基准测试中,Ruby似乎都很慢,比Java慢得多。Ruby的人只是说这无关紧要。您能举个例子说明RubyonRails(以及Ruby本身)的速度真的无关紧要吗?
假设我在我的Rails应用中某处定义了一个名为bla的函数。在ruby或rails中有没有一种方法可以动态/以编程方式打印用于定义该函数的代码?例如:defblaputs"HiThere"end然后如果我调用一个函数,例如get_definition:putsget_definition(:bla)这会打印出来"puts\"HiThere\""有规范的方法吗?我以前实际上不需要这样做,而且我知道这在Rails中并不是很常见的做法。我也不想使用元(反射)编程定义我的方法,然后存储用于定义我的方法的字符串。感谢您的帮助! 最佳答案
我希望Ruby的解析器会进行这种微不足道的优化,但似乎并没有(谈到YARV实现,Ruby1.9.x、2.0.0):require'benchmark'deffib1a,b=0,1whileb由于这两种方法除了在第二种方法中使用预定义常量而不是常量表达式外是相同的,因此Ruby解释器似乎在每个循环中一次又一次地计算幂常数。是否有一些Material说明为什么Ruby根本不进行这种基本优化或只在某些特定情况下进行? 最佳答案 很抱歉给出了另一个答案,但我不想删除或编辑我之前的答案,因为它下面有有趣的讨论。正如JörgWMittag所说,
我正在尝试从数据库中读取大量单元格(超过100.000个)并将它们写入VPSUbuntu服务器上的csv文件。碰巧服务器没有足够的内存。我正在考虑一次读取5000行并将它们写入文件,然后再读取5000行,等等。我应该如何重构我当前的代码以使内存不会被完全消耗?这是我的代码:defwrite_rows(emails)File.open(file_path,"w+")do|f|f该函数由sidekiqworker调用:write_rows(user.emails)感谢您的帮助! 最佳答案 这里的问题是,当您调用emails.each时,