Digest.so implemented

Attached is an implementation of the methods and classes from external
library digest.so that are used by some simple Rails use cases.


I note, that the IronRuby pattern for supporting custom object cloning
it to implement the IDuplicable interface. Is there some reason for this
approach rather than using Ruby’s standard mechanism of implementing an
initialize_copy method? With the latter approach, Ruby programmers can
implement their own copy semantics, eg:

class Foo
def initialize_copy©
puts ‘copying’
end
end
f = Foo.new
g = f.clone

Cheers, Wayne.

2008/2/28, Wayne K. [email protected]:

Attached is an implementation of the methods and classes from external library digest.so that are used by some simple Rails use cases.

This implementation appends all strings hashed to the buffer. Which
means, if you hash 100 MB file, each megabyte incrementally, 100 MB
MutableString is allocated. This is unnecessary, and can be avoided by
using TransformBlock.

FePy’s implementation of hashlib extension module uses this method. See:

You are really on a roll Wayne. Great stuff!

I might be wrong but my impression of the IronRuby support for the
various
.NET interfaces, such as IDuplicable, IEnumerable and so on, was purely
to
support .NET interop and not designed to be the mechanism used by actual
Ruby libraries. So I suppose the most comprehensive method would be to
support both initialize_copy and IDuplicable if you can and then one or
the
other if you can’t (i.e. you are developing only in Ruby or you have a
3rd
party .NET class).

Correct me if I’m wrong.

Pete

incrementally, 100 MB MutableString is allocated. This is
unnecessary, and can be avoided by using TransformBlock.

Hi Seo,

Thanks for raising this. I was aware of the performance issue and my
original implementation did use the TransformBlock method, but I
switched to an explicit buffer approach in order to support cloning of
digest objects. I didn’t think/realize it was possible to clone .NET
Crypto objects.

I see you use the MemberwiseClone method. Firstly, I thought this was a
protected member, how are you able to directly call it on your context
objects? Secondly, is the shallow copy that MemberwiseClone performs
going to give us the correct cloning semantics?

P.S. I notice your module is implemented in Python - I hadn’t even
contemplated the idea of implementing these libraries in Ruby - I guess
because I’m a C# developer. Do people think we should rewrite these
extension libraries in Ruby?

Cheers, Wayne.

2008/2/29, Wayne K. [email protected]:

Thanks for raising this. I was aware of the performance issue and my original implementation did use the TransformBlock method, but I switched to an explicit buffer approach in order to support cloning of digest objects. I didn’t think/realize it was possible to clone .NET Crypto objects.

I see you use the MemberwiseClone method. Firstly, I thought this was a protected member, how are you able to directly call it on your context objects? Secondly, is the shallow copy that MemberwiseClone performs going to give us the correct cloning semantics?

I think visibility is enforced by compiler, not runtime. For example,
one can access private members by reflection or by bytecode
generation. In general, IronPython can access protected members by
default, and private members when explicitly asked.

Hash implementations are fully managed (in .NET and Mono), and shallow
copying by MemberwiseClone does give the correct semantics now.
hashlib.py is currently in production use. However, I don’t think that
MemberwiseClone gives correct semantics is guaranteed by explicit
documentation.

P.S. I notice your module is implemented in Python - I hadn’t even contemplated the idea of implementing these libraries in Ruby - I guess because I’m a C# developer. Do people think we should rewrite these extension libraries in Ruby?

Writing in Ruby does simplify some boilerplates code, doesn’t it?

I thought that the general idea in Ruby circles was that all their
libraries
should be written in Ruby unless there was some important reason not to,
such as performance or access to underlying OS or hardware functionality
that was not available to Ruby code?

The Rubinius guys took this one step further and have pretty much
implemented everything in Ruby (including the runtime engine itself) and
where they needed to access the OS directly they have created hooks into
the
operating system via “special” Rubinius operations that allow the ruby
code
to do the stuff.

Interestingly, they then run into the problem of people monkey patching
their runtime engine by accident, which is what happened when you
required
the math library which changed the way division works in integers and
this
broke their implementation of indexing arrays.

If the DLR is going to compile up the Ruby code into IL anyway then it
should not be a huge performance problem to write most libraries in Ruby
and
then use IR .NET interop to access any underlying functionality that is
not
normally available in Ruby.

**** This would also have the benefit of removing the excuse of non-C#
developers from contributing to the IR libraries!! ****

Pete

Peter Bacon D. wrote:

If the DLR is going to compile up the Ruby code into IL anyway then it
should not be a huge performance problem to write most libraries in Ruby and
then use IR .NET interop to access any underlying functionality that is not
normally available in Ruby.

**** This would also have the benefit of removing the excuse of non-C#
developers from contributing to the IR libraries!! ****

One of the other problems the Rubinius guys face is performance. In
other words, they’re very slow for normal apps because in order for an
all-Ruby set of core classes to perform well, the underlying enging
needs to be much faster than a normal Ruby implementation.

I don’t doubt that IronRuby will be able to achieve really good
performance, as IronPython has done…but I would be very surprised if
it were able to achieve performance high enough to offset the cost of
implementing core classes in Ruby. That said, implementing them in Ruby
first saves you some implementation hassle, and helps the Ruby community
in general by providing implementations that most current and new Ruby
impls should be able to run. But I wouldn’t bank on using those Ruby
versions long term, unless you can afford to swallow the almost-certain
performance hit.

  • Charlie

2008/3/2, Charles Oliver N. [email protected]:

I don’t doubt that IronRuby will be able to achieve really good
performance, as IronPython has done…but I would be very surprised if
it were able to achieve performance high enough to offset the cost of
implementing core classes in Ruby. That said, implementing them in Ruby
first saves you some implementation hassle, and helps the Ruby community
in general by providing implementations that most current and new Ruby
impls should be able to run. But I wouldn’t bank on using those Ruby
versions long term, unless you can afford to swallow the almost-certain
performance hit.

Well, in case of digest.so, I’m not suggesting implementing MD5
algorithm in Ruby (which would be slooow), but implementing the
wrapper around .NET classes in System.Security.Cryptography in Ruby
instead of C#. Performance impact would be negligible.

Implementing as much as possible in Ruby sounds like a plan, because as
you
say it means us Rubyist can avoid C#. As you say, there shouldn’t be any
performance hit as it all gets compiled to IL.

Obviously we need some base parts of the language complete first though
:slight_smile:


Myles E.
Mobile: +61-409-293-183

MadPilot Productions
URL: http://www.madpilot.com.au
Phone: +618-9467-7651
Fax: +618-9467-6289

Try our time tracking system: 88 Miles!

Sanghyeon S.:

Well, in case of digest.so, I’m not suggesting implementing MD5
algorithm in Ruby (which would be slooow), but implementing the wrapper
around .NET classes in System.Security.Cryptography in Ruby instead of
C#. Performance impact would be negligible.

+1 on this. This is the right approach.

Thanks,
-John

RubyMne http://www.jetbrains.com/ruby/ works pretty well.

-Charles

This is very much an ARGH!!!

Time line: Friday get confirmation about an interview using Ruby.
Google for IDE and find Ruby in Steel. Yea (ruby 1.86 in the free
version).

Read the “Book of Ruby” and start my first Ruby application.
For my first application I choose Solve KenKen puzzles.

At some point I need to make a deep copy. I define my initialize_copy
method. The assumption is this will actually be ran, but NO!

I have not looked into implementing the IDuplicable interface. This is
what I ended up doing.

if equation.validEquation
newEquation = equation.clone
newEquation.initialize_copy(newEquation) #should not have to do
this. very anoying
@equations << newEquation # need to make this a deep copy.
end

ARGH!!! ARGH!!!

Is there a free ide that does plain Ruby vs. IronRuby?