From fcec6b5c0d72288aebce9b18e25e6e92772a2eb8 Mon Sep 17 00:00:00 2001 From: nahi Date: Tue, 20 Dec 2011 14:56:07 +0000 Subject: [PATCH] * PStore content update perf optimization. Patch by Masaki Matsushita. See #5248. * lib/pstore.rb (save_data): * Delete inadequate Marshal check. * Deferred file truncation: when writing the new content, truncate the saved file to the data size after writing the data, instead of truncating whole bytes before writing data. * Deferred MD5 calculation: when comparing MD5 hash to check the content modification, calculate MD5 hash of new data iif the content length is differ from the old one. * Compare content size with String#bytesize instead of String#size. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34083 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 19 +++++++++++++++++++ lib/pstore.rb | 34 +++++----------------------------- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index 666f8edc2b..0cc1414929 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +Tue Dec 20 23:50:12 2011 Hiroshi Nakamura + + * PStore content update perf optimization. Patch by Masaki Matsushita. + See #5248. + + * lib/pstore.rb (save_data): + + * Delete inadequate Marshal check. + + * Deferred file truncation: when writing the new content, truncate + the saved file to the data size after writing the data, instead of + truncating whole bytes before writing data. + + * Deferred MD5 calculation: when comparing MD5 hash to check the + content modification, calculate MD5 hash of new data iif the + content length is differ from the old one. + + * Compare content size with String#bytesize instead of String#size. + Tue Dec 20 21:00:30 2011 Tadayoshi Funaba * ext/date/date_core.c: uses to_integer instead. diff --git a/lib/pstore.rb b/lib/pstore.rb index 952445fc93..8f31687c52 100644 --- a/lib/pstore.rb +++ b/lib/pstore.rb @@ -402,11 +402,11 @@ class PStore # This seems to be a newly-created file. table = {} checksum = empty_marshal_checksum - size = empty_marshal_data.size + size = empty_marshal_data.bytesize else table = load(data) checksum = Digest::MD5.digest(data) - size = data.size + size = data.bytesize if !table.is_a?(Hash) raise Error, "PStore file seems to be corrupted." end @@ -427,34 +427,10 @@ class PStore is_windows end - # Check whether Marshal.dump supports the 'canonical' option. This option - # makes sure that Marshal.dump always dumps data structures in the same order. - # This is important because otherwise, the checksums that we generate may differ. - def marshal_dump_supports_canonical_option? - begin - Marshal.dump(nil, -1, true) - result = true - rescue - result = false - end - self.class.instance_method(:marshal_dump_supports_canonical_option?) - self.class.__send__(:define_method, :marshal_dump_supports_canonical_option?) do - result - end - result - end - def save_data(original_checksum, original_file_size, file) - # We only want to save the new data if the size or checksum has changed. - # This results in less filesystem calls, which is good for performance. - if marshal_dump_supports_canonical_option? - new_data = Marshal.dump(@table, -1, true) - else - new_data = dump(@table) - end - new_checksum = Digest::MD5.digest(new_data) + new_data = dump(@table) - if new_data.size != original_file_size || new_checksum != original_checksum + if new_data.bytesize != original_file_size || Digest::MD5.digest(new_data) != original_checksum if @ultra_safe && !on_windows? # Windows doesn't support atomic file renames. save_data_with_atomic_file_rename_strategy(new_data, file) @@ -484,8 +460,8 @@ class PStore def save_data_with_fast_strategy(data, file) file.rewind - file.truncate(0) file.write(data) + file.truncate(data.bytesize) end