Причины этой несоизмеримости в скорости выполнения?

Исходный 'rcs' инструмент все еще там и все еще работает (над Unix и окнами/DOS) и является возможно самым простым из этих инструментов, который является, почему я рекомендовал бы его для работы в команде с двумя людьми в той же системе (например, том же офисе, том же файловом сервере или хосте Unix). Только стоит войти в клиент-серверную модель как подрывная деятельность, если Вы работаете в отдельных средах.

7
задан t_scho 8 December 2009 в 17:35
поделиться

6 ответов

Я обнаружил, что эталонная реализация Ruby (ну, Ruby) (не научно сказано) работает очень медленно.

Если у вас есть возможность, попробуйте запустить вашу программу под JRuby! Чарльз Наттер и другие люди из Sun утверждают, что значительно ускорили Руби.

Я, например, был бы больше всего заинтересован в ваших результатах.

5
ответ дан 6 December 2019 в 21:14
поделиться

Это могло быть потому, что диктовки в Python намного быстрее, чем хэши в Ruby

Я только что провел быстрый тест, построив хэш из 12345678 элемента в Ruby1.8.7 занял 3 раза больше, чем пока Python. Ruby1.9 был примерно вдвое длиннее Python.

Вот как я тестировал
python

$ time python -c "d={}
for i in xrange(12345678):d[i]=1"

ruby ​​

$ time ruby -e "d={};12345678.times{|i|d[i]=1}"

Однако этого недостаточно, чтобы учесть ваше несоответствие.

Возможно, стоит поискать ввод-вывод файлов в - закомментируйте весь хэш-код и посмотрите, сколько времени потребуется пустым циклам для обработки файлов.

Вот еще одна версия на Python с использованием defaultdict и менеджеров контекста

from collections import defaultdict
hashes = defaultdict(int)

with open('c:\\file1.txt', 'r') as f:
    for line in f:
        hashes[line] += 1

print "Done file 1"

with open('c:\\file2.txt', 'r') as f:
    for line in f:
        if line in hashes:
            hashes[line] -= 1
        else:
            print "Hash not found!"

print "Done file 2"

num_errors = 0
for key,value in hashes.items():  # hashes.iteritems() might be better here
    if value != 0:
        print "Uneven hash count: %s" % key
        num_errors += 1

print "Total of %d mismatches found" % num_errors
5
ответ дан 6 December 2019 в 21:14
поделиться

На стороне Python вы можете перебирать элементы словаря следующим образом:

for key, value in hashes.iteritems():
    if value != 0:
        print "Uneven hash count: %s" % key
        num_errors += 1

Также:

for line in f.readlines():
    hashes[line] = hashes.setdefault(line, 0) + 1

... но я не могу помочь вам со стороной Ruby, кроме чтобы предложить вам выследить профилировщика.

2
ответ дан 6 December 2019 в 21:14
поделиться

Мне удалось немного ускорить ваш код Ruby следующим образом:

require 'benchmark'

Benchmark.bm(10) do |x|

  x.report("original version") do
    file = File.open("c:\\file1.txt", "r")
    hashes = {}

    file.each_line { |line|
      if hashes.has_key?(line)
        hashes[line] += 1
      else
        hashes[line] = 1
      end
    }

    file.close()

    #puts "Done file 1"

    not_founds = 0

    file = File.open("c:\\file2.txt", "r")

    file.each_line { |line|
      if hashes.has_key?(line)
        hashes[line] -= 1
      else
        not_founds += 1        
      end
    }

    file.close()

    #puts "Done file 2"

    num_errors = 0
    hashes.each_key{ |key|
      if hashes[key] != 0
        num_errors += 1
      end
    }

    puts "Total of #{not_founds} lines not found in file2"
    puts "Total of #{num_errors} mismatches found"

  end


  x.report("my speedup") do
    hashes = {}
    File.open("c:\\file1.txt", "r") do |f|
      lines = f.readlines
      lines.each { |line|
        if hashes.has_key?(line)
          hashes[line] += 1
        else
          hashes[line] = 1
        end
      }
    end  

    not_founds = 0

    File.open("c:\\file2.txt", "r") do |f|
      lines = f.readlines
      lines.each { |line|
        if hashes.has_key?(line)
          hashes[line] -= 1
        else
          not_founds += 1
        end
      }
    end

    num_errors = hashes.values.to_a.select { |z| z != 0}.size   

    puts "Total of #{not_founds} lines not found in file2"
    puts "Total of #{num_errors} mismatches found"

  end

end

поэтому я читаю файлы одним фрагментом ошибки, в моем случае это немного быстрее (я тестировал в Windows XP, ruby ​​1.8.6 и файл 100000 строк). I benchmarked all different ways to read files (i could think off), and this was the fastest way. Also i did speed up the counting of the values in a hash a bit, but this is only visible if you did it for very large numbers :)

So i get a very small speed-increase here. The output on my machine is as follows:

                user     system      total        real
original versionTotal of 16 lines not found in file2
Total of 4 mismatches found
   1.000000   0.015000   1.015000 (  1.016000)
my speedup v1Total of 16 lines not found in file2
Total of 4 mismatches found
   0.812000   0.047000   0.859000 (  0.859000)

Who has any ideas to improve this further?

If the f.readlines goes slower, because of the size, i found that

File.open("c:\\file2.txt", "r") do |f|
  while (line=f.gets)
    if hashes.has_key?(line)
      hashes[line] -= 1
    else
      not_founds += 1
    end
  end
end

is just a tad quicker for me.

I was thinking about about a way to improve the

if hashes.has_key?(line) ...

code a bit, but could not think of anything.

Have you tried using Ruby 1.9?

I have a Windows 7 Virtual Machine with Ruby 1.9.1, and there the f.readlines was slower, and i needed to use the while (line=f.gets) because of the memory limitations :)

Since a lot uf Ruby users test mainly on Unix related platforms, i guess that could explain why the code is sub-optimal on Windows. Has anybody compared the above mentioned performance on Unix? Is this a ruby vs. python problem, or Ruby-windows vs. Ruby-Unix?

0
ответ дан 6 December 2019 в 21:14
поделиться

I'm not a Ruby expert, so someone please correct me if I'm wrong:

I see a small optimization potential.

If you say

hashes = hash.new(0)

then a reference to an undefined hash will return 0 and store the key; and you can do

hashes[line] += 1

every time, without the enclosing if and else.

Caveat: Untested!

If storing the key doesn't happen automatically, there's yet another hash constructor using a block where you can do it explicitly.

0
ответ дан 6 December 2019 в 21:14
поделиться

Словарь Python очень быстр. См. Как реализованы встроенные словари Python Возможно, Ruby не так уж и хорош.

Я сомневаюсь, что дело в хэш-функциях. У разработчиков Ruby нет возможности создать хеш-функцию, которая на порядок хуже, чем у Python.

Возможно, Ruby 1.8 медленно динамически изменяет размер больших хеш-таблиц? Как ваша проблема масштабируется с файлами меньшего размера?

0
ответ дан 6 December 2019 в 21:14
поделиться