<p><strong>编辑:</strong>我错了,这不是值类型对引用类型的问题。性能问题与散列函数有关,如其他注释中所述。我把答案留在这里是因为有一个有趣的讨论。我的代码部分修复了性能问题,但这不是一个干净和推荐的解决方案。</p>
<p>--</p>
<p>在我的计算机上,我用一个结构替换元组,使您的示例运行速度比运行速度快两倍。这意味着,等价的F#代码应该比Python代码运行得更快。我不同意那些说.NET哈希表速度慢的评论,我相信与Python或其他语言实现没有显著的区别。另外,我不同意“你不能期望1对1的转换代码更快”:对于大多数任务,F代码通常比Python快(静态类型对编译器非常有帮助)。在您的示例中,大部分时间都花在了哈希表查找上,因此可以公平地想象,两种语言<em>都应该</em>几乎一样快。</p>
<p>我认为性能问题与gabage集合有关(但我没有使用探查器进行检查)。这里使用元组比结构慢的原因已经在SO问题(<a href="https://stackoverflow.com/questions/2410710/why-is-the-new-tuple-type-in-net-4-0-a-reference-type-class-and-not-a-value-ty">Why is the new Tuple type in .Net 4.0 a reference type (class) and not a value type (struct)</a>)和MSDN页面(<a href="http://msdn.microsoft.com/en-us/magazine/dd942829.aspx#id0400060" rel="nofollow noreferrer">Building tuples</a>)中讨论过了:</p>
<blockquote>
<p>If they are reference types, this
means there can be lots of garbage
generated if you are changing elements
in a tuple in a tight loop. [...]
F# tuples were reference types, but
there was a feeling from the team that
they could realize a performance
improvement if two, and perhaps three,
element tuples were value types
instead. Some teams that had created
internal tuples had used value instead
of reference types, because their
scenarios were very sensitive to
creating lots of managed objects.</p>
</blockquote>
<p>当然,正如Jon在另一条评论中所说,示例中明显的优化是用数组替换哈希表。数组显然要快得多(整数索引、无散列、无冲突处理、无重新分配、更紧凑),但这是针对您的问题的,它不能解释与Python的性能差异(据我所知,Python代码使用的是散列表,而不是数组)。</p>
<p>为了重现我50%的加速,这里是完整的代码:<a href="http://pastebin.com/nbYrEi5d" rel="nofollow noreferrer">http://pastebin.com/nbYrEi5d</a></p>
<p>简而言之,我用这种类型替换了元组:</p>
<pre><code>type Tup = {x: int; y: int}
</code></pre>
<p>而且,它看起来像一个细节,但是您应该将<code>List.mapi (fun i x -> (i,x)) fileSizes</code>移出封闭循环。我相信Python<code>enumerate</code>实际上并不分配列表(因此在F#中只分配一次列表,或者使用<code>Seq</code>模块,或者使用可变计数器是公平的)。</p>