<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <id>tag:blog.segment7.net,2005:/articles</id>
  <link type="text/html" rel="alternate" href="http://blog.segment7.net"/>
  <link type="application/atom+xml" rel="self" href="http://blog.segment7.net/articles.atom"/>
  <title>Segment7</title>
  <subtitle type="html">The Blog</subtitle>
  <updated>2013-03-27T15:50:49-07:00</updated>
  <generator version="5.x" uri="http://www.typosphere.org">Typo</generator>
  <entry>
    <id>tag:blog.segment7.net,2005:Article/1351</id>
    <published>2013-03-27T15:50:24-07:00</published>
    <updated>2013-03-27T15:50:49-07:00</updated>
    <link type="text/html" rel="alternate" href="http://blog.segment7.net/2013/03/27/rdoc-4-0-1"/>
    <author>
      <name>drbrain</name>
    </author>
    <title type="html">RDoc 4.0.1</title>
    <category label="RDoc" term="rdoc" scheme="http://blog.segment7.net/category/rdoc"/>
    <category label="Software" term="software" scheme="http://blog.segment7.net/category/software"/>
    <content type="html">&lt;ul&gt;
&lt;li&gt;home: https://github.com/rdoc/rdoc&lt;/li&gt;
&lt;li&gt;rdoc: http://docs.seattlerb.org/rdoc&lt;/li&gt;
&lt;li&gt;bugs: https://github.com/rdoc/rdoc/issues&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;RDoc produces HTML and command-line documentation for Ruby projects.  RDoc
includes the +rdoc+ and +ri+ tools for generating and displaying documentation
from the command-line.&lt;/p&gt;

&lt;p&gt;Changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bug fixes

&lt;ul&gt;
&lt;li&gt;RDoc::Options parser should rescue from OptionParser::ParseError.&lt;/li&gt;
&lt;li&gt;Updated example of RDoc::Options to include reopening RDoc::Options. Pointed out by Michael Granger&lt;/li&gt;
&lt;li&gt;Moved RubyGems documentation installed message into RDoc hook.  For RubyGems bug #469 by Jeff Sandberg&lt;/li&gt;
&lt;li&gt;An Error is now raised when a heredoc is not terminated.  Fixes exceptions when processing comment blocks.  Reported by darix&lt;/li&gt;
&lt;li&gt;rdoc --quiet --no-ignore-invalid now exits for invalid options.  Pull request #192 by Jeremy Evans&lt;/li&gt;
&lt;li&gt;RDoc::Parser::C no longer ignores a (METHOD) cast in rb&lt;em&gt;define&lt;/em&gt;method. Pull request #184 by Carlos Agarie&lt;/li&gt;
&lt;li&gt;RDoc::Servlet no longer ignores extra directories from -d.  Pull request #173 by Thomas Leitner&lt;/li&gt;
&lt;li&gt;Fixed &lt;code&gt;rdoc --ri-site&lt;/code&gt;.  Bug #193 by Michal Papis.&lt;/li&gt;
&lt;li&gt;RDoc no longer attempts to parse binary files.  Bug #189 by postmodern, Bug #190 by Christoffer Lerv&#229;g, Bug #195 by Aaron Patterson&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rdoc --pipe&lt;/code&gt; output now contains &lt;code&gt;&lt;/code&gt; for markdown compliance.&lt;/li&gt;
&lt;li&gt;RDoc no longer leaves emacs-style modelines in .txt, .md or .rd files. Bug #178 by Zachary Scott&lt;/li&gt;
&lt;li&gt;RDoc no longer puts raw markup in HTML output for markdown input.  Bug #204 by Erik Hollensbe&lt;/li&gt;
&lt;li&gt;Code objects with nodoc are no longer included in the ri store.  Bug #177 by Thomas Leitner.&lt;/li&gt;
&lt;li&gt;Text#snippet now creates a RDoc::Markup::ToHtmlSnippet correctly.&lt;/li&gt;
&lt;li&gt;The C parser now de-duplicates call-seq if the same C function is used for multiple method names.  Bug #203 by Pete Higgins&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <id>tag:blog.segment7.net,2005:Article/1347</id>
    <published>2013-02-24T09:32:18-08:00</published>
    <updated>2013-02-24T09:46:08-08:00</updated>
    <link type="text/html" rel="alternate" href="http://blog.segment7.net/2013/02/24/rdoc-4-0-0"/>
    <author>
      <name>drbrain</name>
    </author>
    <title type="html">rdoc 4.0.0</title>
    <category label="RDoc" term="rdoc" scheme="http://blog.segment7.net/category/rdoc"/>
    <category label="Software" term="software" scheme="http://blog.segment7.net/category/software"/>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rdoc/rdoc&quot;&gt;home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.seattlerb.org/rdoc&quot;&gt;rdoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rdoc/rdoc/issues&quot;&gt;bugs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;RDoc produces HTML and command-line documentation for Ruby projects.  RDoc
includes the +rdoc+ and +ri+ tools for generating and displaying documentation
from the command-line.&lt;/p&gt;

&lt;h3&gt;Changes&lt;/h3&gt;

&lt;p&gt;RDoc 4.0 includes several new features and several breaking changes.  The
changes should not affect users of &lt;code&gt;rdoc&lt;/code&gt; or &lt;code&gt;ri&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Notable feature additions are markdown support and an WEBrick servlet that can
serve HTML from an ri store.  (This means that RubyGems 2.0+ no longer needs
to build HTML documentation when installing gems.)&lt;/p&gt;

&lt;p&gt;Changes since RDoc 3.12.1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Breaking changes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The default output encoding for RDoc is now UTF-8.  Previously RDoc used
the default external encoding which was determined from your locale.
Issue #106 by Justin Baker.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RDoc::RI::Store is now RDoc::Store so ri data generated by RDoc 4 cannot
be read by earlier versions of RDoc.  RDoc::RI::Store exists as an alias
of RDoc::Store so ri data from older versions can still be read.
RDoc::RI::Store will be removed in RDoc 5.&lt;/p&gt;

&lt;p&gt;Tests that create RDoc::CodeObjects on the fly without wiring them into
the documentation tree (did not use add_class, add_method, etc.) must be
updated to use these methods.  The documentation tree automatically
attaches them to the store instance which allows lookups to work
correctly.  Additionally, a new method RDoc::Store#add_file must be used
instead of RDoc::TopLevel.new.  The latter will not be attached to the
documentation tree.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;RDoc generators must accept an RDoc::Store and an RDoc::Options in
initialize.  RDoc no longer passes an Array of RDoc::TopLevel objects to #generate.  Use RDoc::Store#all_files instead.&lt;/li&gt;
&lt;li&gt;Some markup formatters (RDoc::Markup::To*) now accept an RDoc::Options
instance as the first argument.  Notably, the base class Formatter and
ToHtml*.  (This is not universal due to the difficult at accessing the
user's options instance deep inside RDoc.  A future major release may
remedy this.)&lt;/li&gt;
&lt;li&gt;Added new markup nodes and specials that RDoc::Markup::Formatter
subclasses must handle.  If you're using RDoc::Markup::FormatterTestCase
the new methods you need to add should be readily apparent.&lt;/li&gt;
&lt;li&gt;Removed RDoc::RI::Paths::SYSDIR and ::SITEDIR.  These were hidden
constants so no breakage is expected.  Use RDoc::RI::Paths::system&lt;em&gt;dir
and ::site&lt;/em&gt;dir instead.&lt;/li&gt;
&lt;li&gt;RDoc::RI::Store#modules has been renamed to RDoc::Store#module_names
to avoid confusion with RDoc::Store#all_modules imported from
RDoc::TopLevel.&lt;/li&gt;
&lt;li&gt;RDoc::RDocError has been removed.  It was deprecated throughout RDoc 3.&lt;/li&gt;
&lt;li&gt;ri -f html is no longer supported.&lt;/li&gt;
&lt;li&gt;Comment definitions in C comments are now only discovered from the first
line.  A colon on a subsequent line won't trigger definition extraction.
Issue #103, see also
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/42942&lt;/li&gt;
&lt;li&gt;Fixed :stopdoc: for class A::B where A has not been seen.  Issue #95 by
Ryan Davis&lt;/li&gt;
&lt;li&gt;RDoc::ClassModule#each_ancestor no longer yields itself if there is
circular ancestry&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Major enhancements&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ri can now show pages (README, etc.)&lt;/p&gt;

&lt;p&gt;  ri rdoc:README&lt;/p&gt;

&lt;p&gt;Will show the README for the latest version of RDoc.  You can specify
exact gem versions such as &quot;rdoc-4.0:README&quot; or view pages from the
standard library documentation with &quot;ruby:README&quot;.&lt;/p&gt;

&lt;p&gt;RDoc 3 did not save pages in ri data so you will need to regenerate
documentation from your gems to use this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Added Markdown as a supported format.  The markdown format can be set on a
per-file or per-comment basis with the +:markdown:+ directive like the rd
and tomdoc formats and on a per-project basis with
&lt;tt&gt;rdoc --markup markdown --write-options&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Removed global state from RDoc.  RDoc::Store holds the documentation tree
and connects the driver to the parsers and generator.  This also allows
documentation parsing and generation for multiple instances, but the rdoc
command-line tool does not support this.&lt;/p&gt;

&lt;p&gt;Due to this change RDoc::RDoc.current and RDoc::RDoc.reset no longer
exist.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Minor enhancements&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Added --page-dir option to give pretty names for a FAQ, guides, or other
documentation you write that is not stored in the project root.  For
example, with the following layout:&lt;/p&gt;

&lt;p&gt;  README.txt
  guides/syntax.txt
  guides/conversion.txt&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;rdoc --page-dir guides&lt;/code&gt; will make the files in &quot;guides&quot; appear to
be at the top level of the project.  This means they will appear to exist
at the top level in HTML output and you can access them with
&lt;code&gt;ri your\_gem:syntax&lt;/code&gt; and &lt;code&gt;ri your\_gem:conversion&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Added --root for building documentation from outside the source dir.&lt;/li&gt;
&lt;li&gt;Added current heading and page-top links to HTML headings.&lt;/li&gt;
&lt;li&gt;Added a ChangeLog parser.  It automatically parses files that begin
with 'ChangeLog'&lt;/li&gt;
&lt;li&gt;Added a table of contents to the sidebar.&lt;/li&gt;
&lt;li&gt;RDoc markup format merges adjacent labels in a label or note list into a
single definition list item for output.&lt;/li&gt;
&lt;li&gt;RDoc now tracks use of extend.  Pull request #118 by Michael Granger.&lt;/li&gt;
&lt;li&gt;RDoc now tracks methods that use super.  Pull request #116 by Erik
Hollensbe.&lt;/li&gt;
&lt;li&gt;Added methods ::system&lt;em&gt;dir, ::site&lt;/em&gt;dir, ::home_dir and ::gem_dir to fetch
the components of RDoc::RI::Paths.path individually.&lt;/li&gt;
&lt;li&gt;Added support for rb_file_const.&lt;/li&gt;
&lt;li&gt;RDoc now processes files in sorted order.  Issue #71 by V&#237;t Ondruch&lt;/li&gt;
&lt;li&gt;RDoc now warns with --verbose when methods are duplicated.  Issue #71 by
V&#237;t Ondruch&lt;/li&gt;
&lt;li&gt;ri will display documentation for all methods in a class if -a is given.
Issue #57 by casper&lt;/li&gt;
&lt;li&gt;The RDoc coverage report will report line information for attributes,
constants and methods missing documentation.  Issue #121 by Zachary Scott&lt;/li&gt;
&lt;li&gt;RDoc now reports a warning for files that are unreadable due to
permissions problems.&lt;/li&gt;
&lt;li&gt;RDoc controls documentation generation for RubyGems 2.0+&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bug fixes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixed parsing of multibyte files with incomplete characters at byte 1024.
Ruby bug #6393 by nobu, patch by Nobuyoshi Nakada and Yui NARUSE.&lt;/li&gt;
&lt;li&gt;Fixed rdoc -E.  Ruby Bug #6392 and (modified) patch by Nobuyoshi Nakada&lt;/li&gt;
&lt;li&gt;Added link handling to Markdown output.  Bug #160 by burningTyger.&lt;/li&gt;
&lt;li&gt;Fixed HEREDOC output for the limited case of a heredoc followed by a line
end.  When a HEREDOC is not followed by a line end RDoc is not currently
smart enough to restore the source correctly.  Bug #162 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Fixed parsing of executables with shebang and encoding comments.  Bug #161
by Marcus Stollsteimer&lt;/li&gt;
&lt;li&gt;RDoc now ignores methods defined on constants instead of creating a fake
module.  Bug #163 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Fixed ChangeLog parsing for FFI gem.  Bug #165 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;RDoc now links #=== methods.  Bug #164 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Allow [] following argument names for TomDoc.  Bug #167 by Ellis Berner.&lt;/li&gt;
&lt;li&gt;Fixed the RDoc servlet for home and site directories.  Bug #170 by Thomas
Leitner.&lt;/li&gt;
&lt;li&gt;Fixed references to methods in the RDoc servlet.  Bug #171 by Thomas
Leitner.&lt;/li&gt;
&lt;li&gt;Fixed debug message when generating the darkfish root page.  Pull Request #174 by Thomas Leitner.&lt;/li&gt;
&lt;li&gt;Fixed deletion of attribute ri data when a class was loaded then saved.
Issue #171 by Thomas Leitner.&lt;/li&gt;
&lt;li&gt;Fully qualified names for constants declared from the top level are now
attached to their class or module properly.&lt;/li&gt;
&lt;li&gt;Fixed table of contents display in HTML output for classes and modules.&lt;/li&gt;
&lt;li&gt;Incremental ri builds of C files now work.  C variable names from previous
runs are now saved between runs.&lt;/li&gt;
&lt;li&gt;A word that is directly followed by a multi-word tidy link label no longer
disappears.  (Like &lt;code&gt;text{link}[http://example]&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Fixed legacy template support.  Pull Request #107 by Justin Baker.&lt;/li&gt;
&lt;li&gt;An HTML class in a verbatim section no longer triggers ruby parsing.
Issue #92 by Vijay Dev&lt;/li&gt;
&lt;li&gt;Improved documentation for setting the default documentation format for
your ruby project.  Issue #94 by Henrik Hodne&lt;/li&gt;
&lt;li&gt;Fixed handling of LANG in the RDoc::Options tests.  Issue #99 by V&#237;t
Ondruch&lt;/li&gt;
&lt;li&gt;RDoc no longer quits when given an entry that is not a file or directory.
Issue #101 by Charles Nutter&lt;/li&gt;
&lt;li&gt;Fixed bug in syntax-highlighting that would corrupt regular expressions.
Ruby Bug #6488 by Benny Lyne Amorsen.&lt;/li&gt;
&lt;li&gt;&quot;class Object&quot; no longer appears in the coverage report if all its methods
are documented.  This suppresses a false positive for libraries that add
toplevel methods.  Pull Request #128 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Fixed test&lt;em&gt;gen&lt;/em&gt;url test name in TestRDocMarkupToHtml.  Pull Request #130
by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Comment-defined methods ahead of define_method are now discovered.  Issue #133 by eclectic923&lt;/li&gt;
&lt;li&gt;Fixed detection of define_method documentation.  Issue #138 by Marvin
G&#252;lker.&lt;/li&gt;
&lt;li&gt;Fixed lexing of character syntax (&lt;code&gt;?z&lt;/code&gt;).  Reported by Xavier
Noria.&lt;/li&gt;
&lt;li&gt;Add license to gem spec.  Issue #144 by pivotalcommon&lt;/li&gt;
&lt;li&gt;Fixed comment selection for classes.  Pull request #146 by pioz&lt;/li&gt;
&lt;li&gt;Fixed parsing of &lt;code&gt;def self.&amp;amp;() end&lt;/code&gt;.  Issue #148 by Michael
Lucy&lt;/li&gt;
&lt;li&gt;Generated RD parser files are now included in the gem.  Issue #145 by
Marvin G&#252;lker&lt;/li&gt;
&lt;li&gt;Class and module aliases now create new classes to avoid duplicate names
in the class list.  Issue #143 by Richard Schneeman, Rails Issue #2839&lt;/li&gt;
&lt;li&gt;RDoc::Markup::Parser now correctly matches indentation of lists when
multibyte characters are used in the list labels.  Issue #140 by
burningTyger&lt;/li&gt;
&lt;li&gt;Fixed mangling of email addresses that look like labels.  Issue #129 by
Tobias Koch&lt;/li&gt;
&lt;li&gt;Classes and modules in a C file may now be created in any order.  Issue #124 by Su Zhang&lt;/li&gt;
&lt;li&gt;A metaprogrammed method supports the :args: directive.  Issue #100&lt;/li&gt;
&lt;li&gt;A metaprogrammed method supports the :yields: directive.&lt;/li&gt;
&lt;li&gt;RDoc will now look for directives up to the end of the line.  For example,
  class B &amp;lt; A; end # :nodoc:
will now hide documentation of B.  Issue #125 by Zachary Scott&lt;/li&gt;
&lt;li&gt;Fixed tokenization of % when it is not followed by a $-string type&lt;/li&gt;
&lt;li&gt;Fixed display of _&lt;em&gt;END_&lt;/em&gt; in documentation examples in HTML output&lt;/li&gt;
&lt;li&gt;Fixed tokenization of reserved words used as new-style hash keys&lt;/li&gt;
&lt;li&gt;RDoc now handles class &amp;lt;&amp;lt; $gvar by ignoring the body&lt;/li&gt;
&lt;li&gt;Fixed parsing of class A:: B.&lt;/li&gt;
&lt;li&gt;Worked around bug in RDoc::RubyLex where tokens won't be reinterpreted
after unget_tk.&lt;/li&gt;
&lt;li&gt;Fixed class &amp;lt;&amp;lt; ::Foo writing documentation to /Foo.html&lt;/li&gt;
&lt;li&gt;Fixed class ::A referencing itself from inside its own namespace.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Changes since RDoc 4.0.0.rc.2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bug fix

&lt;ul&gt;
&lt;li&gt;Templates now use the correct encoding when generating pages.  Issue #183
by V&#237;t Ondruch&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <id>tag:blog.segment7.net,2005:Article/1344</id>
    <published>2013-02-08T15:02:34-08:00</published>
    <updated>2013-02-08T15:10:38-08:00</updated>
    <link type="text/html" rel="alternate" href="http://blog.segment7.net/2013/02/08/rdoc-4-0-0-rc-2-1"/>
    <author>
      <name>drbrain</name>
    </author>
    <title type="html">RDoc 4.0.0.rc.2.1</title>
    <category label="RDoc" term="rdoc" scheme="http://blog.segment7.net/category/rdoc"/>
    <category label="Software" term="software" scheme="http://blog.segment7.net/category/software"/>
    <content type="html">&lt;p&gt;As a preview release, please file bugs for any problems you have with rdoc at
https://github.com/rdoc/rdoc/issues&lt;/p&gt;

&lt;p&gt;RDoc 4.0 includes several new features and several breaking changes.  The
changes should not affect users of &lt;code&gt;rdoc&lt;/code&gt; or &lt;code&gt;ri&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Notable feature additions are markdown support and an WEBrick servlet that can
serve HTML from an ri store.  (This means that RubyGems 2.0+ no longer needs
to build HTML documentation when installing gems.)&lt;/p&gt;

&lt;p&gt;Changes since RDoc 3.12.1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Breaking changes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The default output encoding for RDoc is now UTF-8.  Previously RDoc used
the default external encoding which was determined from your locale.
Issue #106 by Justin Baker.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;RDoc::RI::Store is now RDoc::Store so ri data generated by RDoc 4 cannot
be read by earlier versions of RDoc.  RDoc::RI::Store exists as an alias
of RDoc::Store so ri data from older versions can still be read.
RDoc::RI::Store will be removed in RDoc 5.&lt;/p&gt;

&lt;p&gt;Tests that create RDoc::CodeObjects on the fly without wiring them into
the documentation tree (did not use add&lt;em&gt;class, add&lt;/em&gt;method, etc.) must be
updated to use these methods.  The documentation tree automatically
attaches them to the store instance which allows lookups to work
correctly.  Additionally, a new method RDoc::Store#add_file must be used
instead of RDoc::TopLevel.new.  The latter will not be attached to the
documentation tree.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;RDoc generators must accept an RDoc::Store and an RDoc::Options in
initialize.  RDoc no longer passes an Array of RDoc::TopLevel objects to #generate.  Use RDoc::Store#all_files instead.&lt;/li&gt;
&lt;li&gt;Some markup formatters (RDoc::Markup::To&lt;em&gt;) now accept an RDoc::Options
instance as the first argument.  Notably, the base class Formatter and
ToHtml&lt;/em&gt;.  (This is not universal due to the difficult at accessing the
user's options instance deep inside RDoc.  A future major release may
remedy this.)&lt;/li&gt;
&lt;li&gt;Added new markup nodes and specials that RDoc::Markup::Formatter
subclasses must handle.  If you're using RDoc::Markup::FormatterTestCase
the new methods you need to add should be readily apparent.&lt;/li&gt;
&lt;li&gt;Removed RDoc::RI::Paths::SYSDIR and ::SITEDIR.  These were hidden
constants so no breakage is expected.  Use RDoc::RI::Paths::system&lt;em&gt;dir
and ::site&lt;/em&gt;dir instead.&lt;/li&gt;
&lt;li&gt;RDoc::RI::Store#modules has been renamed to RDoc::Store#module&lt;em&gt;names
to avoid confusion with RDoc::Store#all&lt;/em&gt;modules imported from
RDoc::TopLevel.&lt;/li&gt;
&lt;li&gt;RDoc::RDocError has been removed.  It was deprecated throughout RDoc 3.&lt;/li&gt;
&lt;li&gt;ri -f html is no longer supported.&lt;/li&gt;
&lt;li&gt;Comment definitions in C comments are now only discovered from the first
line.  A colon on a subsequent line won't trigger definition extraction.
Issue #103, see also
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/42942&lt;/li&gt;
&lt;li&gt;Fixed :stopdoc: for class A::B where A has not been seen.  Issue #95 by
Ryan Davis&lt;/li&gt;
&lt;li&gt;RDoc::ClassModule#each_ancestor no longer yields itself if there is
circular ancestry&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Major enhancements&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ri can now show pages (README, etc.)&lt;/p&gt;

&lt;p&gt;  ri rdoc:README&lt;/p&gt;

&lt;p&gt;Will show the README for the latest version of RDoc.  You can specify
exact gem versions such as &quot;rdoc-4.0:README&quot; or view pages from the
standard library documentation with &quot;ruby:README&quot;.&lt;/p&gt;

&lt;p&gt;RDoc 3 did not save pages in ri data so you will need to regenerate
documentation from your gems to use this feature.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Added Markdown as a supported format.  The markdown format can be set on a
per-file or per-comment basis with the +:markdown:+ directive like the rd
and tomdoc formats and on a per-project basis with
&lt;tt&gt;rdoc --markup markdown --write-options&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Removed global state from RDoc.  RDoc::Store holds the documentation tree
and connects the driver to the parsers and generator.  This also allows
documentation parsing and generation for multiple instances, but the rdoc
command-line tool does not support this.&lt;/p&gt;

&lt;p&gt;Due to this change RDoc::RDoc.current and RDoc::RDoc.reset no longer
exist.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Minor enhancements&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Added --page-dir option to give pretty names for a FAQ, guides, or other
documentation you write that is not stored in the project root.  For
example, with the following layout:&lt;/p&gt;

&lt;p&gt;  README.txt
  guides/syntax.txt
  guides/conversion.txt&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;rdoc --page-dir guides&lt;/code&gt; will make the files in &quot;guides&quot; appear to
be at the top level of the project.  This means they will appear to exist
at the top level in HTML output and you can access them with
&lt;code&gt;ri your_gem:syntax&lt;/code&gt; and &lt;code&gt;ri your_gem:conversion&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;Added --root for building documentation from outside the source dir.&lt;/li&gt;
&lt;li&gt;Added current heading and page-top links to HTML headings.&lt;/li&gt;
&lt;li&gt;Added a ChangeLog parser.  It automatically parses files that begin
with 'ChangeLog'&lt;/li&gt;
&lt;li&gt;Added a table of contents to the sidebar.&lt;/li&gt;
&lt;li&gt;RDoc markup format merges adjacent labels in a label or note list into a
single definition list item for output.&lt;/li&gt;
&lt;li&gt;RDoc now tracks use of extend.  Pull request #118 by Michael Granger.&lt;/li&gt;
&lt;li&gt;RDoc now tracks methods that use super.  Pull request #116 by Erik
Hollensbe.&lt;/li&gt;
&lt;li&gt;Added methods ::system&lt;em&gt;dir, ::site&lt;/em&gt;dir, ::home&lt;em&gt;dir and ::gem&lt;/em&gt;dir to fetch
the components of RDoc::RI::Paths.path individually.&lt;/li&gt;
&lt;li&gt;Added support for rb&lt;em&gt;file&lt;/em&gt;const.&lt;/li&gt;
&lt;li&gt;RDoc now processes files in sorted order.  Issue #71 by V&#237;t Ondruch&lt;/li&gt;
&lt;li&gt;RDoc now warns with --verbose when methods are duplicated.  Issue #71 by
V&#237;t Ondruch&lt;/li&gt;
&lt;li&gt;ri will display documentation for all methods in a class if -a is given.
Issue #57 by casper&lt;/li&gt;
&lt;li&gt;The RDoc coverage report will report line information for attributes,
constants and methods missing documentation.  Issue #121 by Zachary Scott&lt;/li&gt;
&lt;li&gt;RDoc now reports a warning for files that are unreadable due to
permissions problems.&lt;/li&gt;
&lt;li&gt;RDoc controls documentation generation for RubyGems 2.0+&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bug fixes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixed parsing of multibyte files with incomplete characters at byte 1024.
Ruby bug #6393 by nobu, patch by Nobuyoshi Nakada and Yui NARUSE.&lt;/li&gt;
&lt;li&gt;Fixed rdoc -E.  Ruby Bug #6392 and (modified) patch by Nobuyoshi Nakada&lt;/li&gt;
&lt;li&gt;Added link handling to Markdown output.  Bug #160 by burningTyger.&lt;/li&gt;
&lt;li&gt;Fixed HEREDOC output for the limited case of a heredoc followed by a line
end.  When a HEREDOC is not followed by a line end RDoc is not currently
smart enough to restore the source correctly.  Bug #162 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Fixed parsing of executables with shebang and encoding comments.  Bug #161
by Marcus Stollsteimer&lt;/li&gt;
&lt;li&gt;RDoc now ignores methods defined on constants instead of creating a fake
module.  Bug #163 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Fixed ChangeLog parsing for FFI gem.  Bug #165 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;RDoc now links #=== methods.  Bug #164 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Allow [] following argument names for TomDoc.  Bug #167 by Ellis Berner.&lt;/li&gt;
&lt;li&gt;Fixed the RDoc servlet for home and site directories.  Bug #170 by Thomas
Leitner.&lt;/li&gt;
&lt;li&gt;Fixed references to methods in the RDoc servlet.  Bug #171 by Thomas
Leitner.&lt;/li&gt;
&lt;li&gt;Fixed debug message when generating the darkfish root page.  Pull Request #174 by Thomas Leitner.&lt;/li&gt;
&lt;li&gt;Fixed deletion of attribute ri data when a class was loaded then saved.
Issue #171 by Thomas Leitner.&lt;/li&gt;
&lt;li&gt;Fully qualified names for constants declared from the top level are now
attached to their class or module properly.&lt;/li&gt;
&lt;li&gt;Fixed table of contents display in HTML output for classes and modules.&lt;/li&gt;
&lt;li&gt;Incremental ri builds of C files now work.  C variable names from previous
runs are now saved between runs.&lt;/li&gt;
&lt;li&gt;A word that is directly followed by a multi-word tidy link label no longer
disappears.  (Like &lt;code&gt;text{link}[http://example]&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Fixed legacy template support.  Pull Request #107 by Justin Baker.&lt;/li&gt;
&lt;li&gt;An HTML class in a verbatim section no longer triggers ruby parsing.
Issue #92 by Vijay Dev&lt;/li&gt;
&lt;li&gt;Improved documentation for setting the default documentation format for
your ruby project.  Issue #94 by Henrik Hodne&lt;/li&gt;
&lt;li&gt;Fixed handling of LANG in the RDoc::Options tests.  Issue #99 by V&#237;t
Ondruch&lt;/li&gt;
&lt;li&gt;RDoc no longer quits when given an entry that is not a file or directory.
Issue #101 by Charles Nutter&lt;/li&gt;
&lt;li&gt;Fixed bug in syntax-highlighting that would corrupt regular expressions.
Ruby Bug #6488 by Benny Lyne Amorsen.&lt;/li&gt;
&lt;li&gt;&quot;class Object&quot; no longer appears in the coverage report if all its methods
are documented.  This suppresses a false positive for libraries that add
toplevel methods.  Pull Request #128 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Fixed test&lt;em&gt;gen&lt;/em&gt;url test name in TestRDocMarkupToHtml.  Pull Request #130
by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Comment-defined methods ahead of define_method are now discovered.  Issue #133 by eclectic923&lt;/li&gt;
&lt;li&gt;Fixed detection of define_method documentation.  Issue #138 by Marvin
G&#252;lker.&lt;/li&gt;
&lt;li&gt;Fixed lexing of character syntax (&lt;code&gt;?z&lt;/code&gt;).  Reported by Xavier
Noria.&lt;/li&gt;
&lt;li&gt;Add license to gem spec.  Issue #144 by pivotalcommon&lt;/li&gt;
&lt;li&gt;Fixed comment selection for classes.  Pull request #146 by pioz&lt;/li&gt;
&lt;li&gt;Fixed parsing of &lt;code&gt;def self.&amp;amp;() end&lt;/code&gt;.  Issue #148 by Michael
Lucy&lt;/li&gt;
&lt;li&gt;Generated RD parser files are now included in the gem.  Issue #145 by
Marvin G&#252;lker&lt;/li&gt;
&lt;li&gt;Class and module aliases now create new classes to avoid duplicate names
in the class list.  Issue #143 by Richard Schneeman, Rails Issue #2839&lt;/li&gt;
&lt;li&gt;RDoc::Markup::Parser now correctly matches indentation of lists when
multibyte characters are used in the list labels.  Issue #140 by
burningTyger&lt;/li&gt;
&lt;li&gt;Fixed mangling of email addresses that look like labels.  Issue #129 by
Tobias Koch&lt;/li&gt;
&lt;li&gt;Classes and modules in a C file may now be created in any order.  Issue #124 by Su Zhang&lt;/li&gt;
&lt;li&gt;A metaprogrammed method supports the :args: directive.  Issue #100&lt;/li&gt;
&lt;li&gt;A metaprogrammed method supports the :yields: directive.&lt;/li&gt;
&lt;li&gt;RDoc will now look for directives up to the end of the line.  For example,
    class B &amp;lt; A; end # :nodoc:
will now hide documentation of B.  Issue #125 by Zachary Scott&lt;/li&gt;
&lt;li&gt;Fixed tokenization of % when it is not followed by a $-string type&lt;/li&gt;
&lt;li&gt;Fixed display of &lt;strong&gt;END&lt;/strong&gt; in documentation examples in HTML output&lt;/li&gt;
&lt;li&gt;Fixed tokenization of reserved words used as new-style hash keys&lt;/li&gt;
&lt;li&gt;RDoc now handles class &amp;lt;&amp;lt; $gvar by ignoring the body&lt;/li&gt;
&lt;li&gt;Fixed parsing of class A:: B.&lt;/li&gt;
&lt;li&gt;Worked around bug in RDoc::RubyLex where tokens won't be reinterpreted
after unget_tk.&lt;/li&gt;
&lt;li&gt;Fixed class &amp;lt;&amp;lt; ::Foo writing documentation to /Foo.html&lt;/li&gt;
&lt;li&gt;Fixed class ::A referencing itself from inside its own namespace.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Changes since RDoc 4.0.0.rc.2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bug fix

&lt;ul&gt;
&lt;li&gt;Templates now use the correct encoding when generating pages.  Issue #183
by V&#237;t Ondruch&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <id>tag:blog.segment7.net,2005:Article/1343</id>
    <published>2013-02-06T10:36:20-08:00</published>
    <updated>2013-02-06T11:01:25-08:00</updated>
    <link type="text/html" rel="alternate" href="http://blog.segment7.net/2013/02/06/rdoc-xss-vulnerability-cve-2013-0256-releases-3-9-5-3-12-1-4-0-0-rc-2"/>
    <author>
      <name>drbrain</name>
    </author>
    <title type="html">RDoc XSS vulnerability CVE-2013-0256 releases 3.9.5, 3.12.1, 4.0.0.rc.2</title>
    <category label="RDoc" term="rdoc" scheme="http://blog.segment7.net/category/rdoc"/>
    <category label="Software" term="software" scheme="http://blog.segment7.net/category/software"/>
    <content type="html">&lt;p&gt;RDoc versions 3.9.5, 3.12.1 and 4.0.0.rc.2 have been released!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;home: &lt;a href=&quot;https://github.com/rdoc/rdoc&quot;&gt;github.com/rdoc/rdoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;rdoc: &lt;a href=&quot;http://docs.seattlerb.org/rdoc&quot;&gt;docs.seattlerb.org/rdoc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;bugs: &lt;a href=&quot;https://github.com/rdoc/rdoc/issues&quot;&gt;github.com/rdoc/rdoc/issues&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;RDoc produces HTML and command-line documentation for Ruby projects.  RDoc
includes the &lt;code&gt;rdoc&lt;/code&gt; and &lt;code&gt;ri&lt;/code&gt; tools for generating and
displaying documentation from the command-line.&lt;/p&gt;

&lt;h3&gt;Vulnerability Description&lt;/h3&gt;

&lt;p&gt;RDoc documentation generated by rdoc 2.3.0 through rdoc 3.12 and prereleases up
to rdoc 4.0.0.preview2.1 are vulnerable to an XSS exploit.  This exploit may
lead to cookie disclosure to third parties.&lt;/p&gt;

&lt;p&gt;The exploit exists in darkfish.js which is copied from the RDoc install
location to the generated documentation.&lt;/p&gt;

&lt;p&gt;RDoc is a static documentation generation tool.  Patching the library itself
is insufficient to correct this exploit.  Those hosting rdoc documentation will
need to apply the following patch.  If applied while ignoring whitespace, this
patch will correct all affected versions:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;diff --git darkfish.js darkfish.js
index 4be722f..f26fd45 100644
--- darkfish.js
+++ darkfish.js
@@ -109,13 +109,15 @@ function hookSearch() {
 function highlightTarget( anchor ) {
   console.debug( &quot;Highlighting target '%s'.&quot;, anchor );

-  $(&quot;a[name=&quot; + anchor + &quot;]&quot;).each( function() {
-    if ( !$(this).parent().parent().hasClass('target-section') ) {
-      console.debug( &quot;Wrapping the target-section&quot; );
-      $('div.method-detail').unwrap( 'div.target-section' );
-      $(this).parent().wrap( '&amp;lt;div class=&quot;target-section&quot;&amp;gt;&amp;lt;/div&amp;gt;' );
-    } else {
-      console.debug( &quot;Already wrapped.&quot; );
+  $(&quot;a[name]&quot;).each( function() {
+    if ( $(this).attr(&quot;name&quot;) == anchor ) {
+      if ( !$(this).parent().parent().hasClass('target-section') ) {
+        console.debug( &quot;Wrapping the target-section&quot; );
+        $('div.method-detail').unwrap( 'div.target-section' );
+        $(this).parent().wrap( '&amp;lt;div class=&quot;target-section&quot;&amp;gt;&amp;lt;/div&amp;gt;' );
+      } else {
+        console.debug( &quot;Already wrapped.&quot; );
+      }
     }
   });
 };
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;RDoc 3.9.5, 3.12.1 and RDoc 4.0.0.rc.2 and newer are not vulnerable to this
exploit.&lt;/p&gt;

&lt;p&gt;This exploit was discovered by Evgeny Ermakov &lt;a href=&quot;&amp;#x6d;&amp;#97;&amp;#x69;&amp;#108;&amp;#116;&amp;#111;&amp;#58;&amp;#99;&amp;#x6f;&amp;#x72;&amp;#119;&amp;#x6d;&amp;#104;&amp;#64;&amp;#103;&amp;#109;&amp;#x61;&amp;#105;&amp;#108;&amp;#46;&amp;#99;&amp;#x6f;&amp;#x6d;&quot;&gt;&amp;#99;&amp;#111;&amp;#114;&amp;#x77;&amp;#x6d;&amp;#x68;&amp;#64;&amp;#x67;&amp;#109;&amp;#97;&amp;#105;&amp;#x6c;&amp;#46;&amp;#99;&amp;#x6f;&amp;#x6d;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This vulnerability has been assigned the CVE identifier CVE-2013-0256.&lt;/p&gt;

&lt;h3&gt;RDoc 3.9.5&lt;/h3&gt;

&lt;p&gt;RDoc 3.9.5 was released to match the RDoc in &lt;a href=&quot;http://www.ruby-lang.org/en/news/2013/02/06/ruby-1-9-3-p385-is-released/&quot;&gt;ruby 1.9.3-p385&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bug fixes

&lt;ul&gt;
&lt;li&gt;Fixed an XSS exploit in darkfish.js.  This could lead to cookie disclosure
to third parties.  See CVE-2013-0256.rdoc for full details including a
patch you can apply to generated RDoc documentation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;RDoc 3.12.1&lt;/h3&gt;

&lt;p&gt;RDoc 3.12.1 was updated as the latest stable release as RDoc 4 is not yet ready.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bug fixes

&lt;ul&gt;
&lt;li&gt;Fixed an XSS exploit in darkfish.js.  This could lead to cookie disclosure
to third parties.  See CVE-2013-0256.rdoc for full
details including a patch you can apply to generated RDoc documentation.&lt;/li&gt;
&lt;li&gt;Ensured that rd parser files are generated before checking the manifest.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;RDoc 4.0.0.rc.2&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Minor enhancements&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Added current heading and page-top links to HTML headings.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bug fixes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixed an XSS exploit in darkfish.js.  This could lead to cookie disclosure
to third parties.  See CVE-2013-0256.rdoc for full
details including a patch you can apply to generated RDoc documentation.&lt;/li&gt;
&lt;li&gt;Fixed parsing of multibyte files with incomplete characters at byte 1024.
Ruby bug #6393 by nobu, patch by Nobuyoshi Nakada and Yui NARUSE.&lt;/li&gt;
&lt;li&gt;Fixed rdoc -E.  Ruby Bug #6392 and (modified) patch by Nobuyoshi Nakada&lt;/li&gt;
&lt;li&gt;Added link handling to Markdown output.  Bug #160 by burningTyger.&lt;/li&gt;
&lt;li&gt;Fixed HEREDOC output for the limited case of a heredoc followed by a line
end.  When a HEREDOC is not followed by a line end RDoc is not currently
smart enough to restore the source correctly.  Bug #162 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Fixed parsing of executables with shebang and encoding comments.  Bug #161
by Marcus Stollsteimer&lt;/li&gt;
&lt;li&gt;RDoc now ignores methods defined on constants instead of creating a fake
module.  Bug #163 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Fixed ChangeLog parsing for FFI gem.  Bug #165 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;RDoc now links #=== methods.  Bug #164 by Zachary Scott.&lt;/li&gt;
&lt;li&gt;Allow [] following argument names for TomDoc.  Bug #167 by Ellis Berner.&lt;/li&gt;
&lt;li&gt;Fixed the RDoc servlet for home and site directories.  Bug #170 by Thomas
Leitner.&lt;/li&gt;
&lt;li&gt;Fixed references to methods in the RDoc servlet.  Bug #171 by Thomas
Leitner.&lt;/li&gt;
&lt;li&gt;Fixed debug message when generating the darkfish root page.  Pull Request #174 by Thomas Leitner.&lt;/li&gt;
&lt;li&gt;Fixed deletion of attribute ri data when a class was loaded then saved.
Issue #171 by Thomas Leitner.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <id>tag:blog.segment7.net,2005:Article/1342</id>
    <published>2012-12-01T12:51:06-08:00</published>
    <updated>2012-12-01T12:52:17-08:00</updated>
    <link type="text/html" rel="alternate" href="http://blog.segment7.net/2012/12/01/rdoc-4-0-0-preview2"/>
    <author>
      <name>drbrain</name>
    </author>
    <title type="html">RDoc 4.0.0.preview2</title>
    <content type="html">
&lt;p&gt;rdoc version 4.0.0.preview2 has been released!&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;home: &lt;a href=&quot;https://github.com/rdoc/rdoc&quot;&gt;github.com/rdoc/rdoc&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;rdoc: &lt;a href=&quot;http://docs.seattlerb.org/rdoc&quot;&gt;docs.seattlerb.org/rdoc&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;bugs: &lt;a
href=&quot;https://github.com/rdoc/rdoc/issues&quot;&gt;github.com/rdoc/rdoc/issues&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;RDoc produces HTML and command-line documentation for Ruby projects.  RDoc
includes the &lt;code&gt;rdoc&lt;/code&gt; and &lt;code&gt;ri&lt;/code&gt; tools for generating and
displaying documentation from the command-line.&lt;/p&gt;

&lt;p&gt;Changes:&lt;/p&gt;

&lt;h3 id=&quot;label-4.0.0.preview2&quot;&gt;4.0.0.preview2&lt;/h3&gt;

&lt;p&gt;As a preview release, please file bugs for any problems you have with rdoc
at &lt;a
href=&quot;https://github.com/rdoc/rdoc/issues&quot;&gt;github.com/rdoc/rdoc/issues&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RDoc 4.0 includes several new features and several breaking changes.  The
changes should not affect users of `rdoc` or `ri`.&lt;/p&gt;

&lt;p&gt;Notable feature additions are markdown support and an WEBrick servlet that
can serve HTML from an ri store.  (This means that RubyGems 2.0+ no longer
needs to build HTML documentation when installing gems.)&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;Breaking changes&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;The default output encoding for RDoc is now UTF-8.  Previously RDoc used
the default external encoding which was determined from your locale. Issue
#106 by Justin Baker.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc::RI::Store is now RDoc::Store so ri data generated by RDoc 4 cannot be
read by earlier versions of RDoc.  RDoc::RI::Store exists as an alias of
RDoc::Store so ri data from older versions can still be read.
RDoc::RI::Store will be removed in RDoc 5.&lt;/p&gt;

&lt;p&gt;Tests that create RDoc::CodeObjects on the fly without wiring them into the
documentation tree (did not use add_class, add_method, etc.) must be
updated to use these methods.  The documentation tree automatically
attaches them to the store instance which allows lookups to work correctly.
Additionally, a new method RDoc::Store#add_file must be used instead of
RDoc::TopLevel.new.  The latter will not be attached to the documentation
tree.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc generators must accept an RDoc::Store and an RDoc::Options in
initialize.  RDoc no longer passes an Array of RDoc::TopLevel objects to
#generate.  Use RDoc::Store#all_files instead.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Some markup formatters (RDoc::Markup::To*) now accept an RDoc::Options
instance as the first argument.  Notably, the base class Formatter and
ToHtml*.  (This is not universal due to the difficult at accessing the
user&amp;#39;s options instance deep inside RDoc.  A future major release may
remedy this.)&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Added new markup nodes and specials that RDoc::Markup::Formatter subclasses
must handle.  If you&amp;#39;re using RDoc::Markup::FormatterTestCase the new
methods you need to add should be readily apparent.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Removed RDoc::RI::Paths::SYSDIR and ::SITEDIR.  These were hidden constants
so no breakage is expected.  Use RDoc::RI::Paths::system_dir and ::site_dir
instead.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc::RI::Store#modules has been renamed to RDoc::Store#module_names to
avoid confusion with RDoc::Store#all_modules imported from RDoc::TopLevel.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc::RDocError has been removed.  It was deprecated throughout RDoc 3.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;ri -f html is no longer supported.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Comment definitions in C comments are now only discovered from the first
line.  A colon on a subsequent line won&amp;#39;t trigger definition
extraction. Issue #103, see also &lt;a
href=&quot;http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/42942&quot;&gt;blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/42942&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed :stopdoc: for class A::B where A has not been seen.  Issue #95 by
Ryan Davis&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc::ClassModule#each_ancestor no longer yields itself if there is
circular ancestry&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Major enhancements&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;ri can now show pages (README, etc.)&lt;/p&gt;

&lt;pre&gt;ri rdoc:README&lt;/pre&gt;

&lt;p&gt;Will show the README for the latest version of RDoc.  You can specify exact
gem versions such as &#8220;rdoc-4.0:README&#8221; or view pages from the standard
library documentation with &#8220;ruby:README&#8221;.&lt;/p&gt;

&lt;p&gt;RDoc 3 did not save pages in ri data so you will need to regenerate
documentation from your gems to use this feature.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Added Markdown as a supported format.  The markdown format can be set on a
per-file or per-comment basis with the &lt;code&gt;:markdown:&lt;/code&gt; directive
like the rd and tomdoc formats and on a per-project basis with &lt;code&gt;rdoc
--markup markdown --write-options&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Removed global state from RDoc.  RDoc::Store holds the documentation tree
and connects the driver to the parsers and generator.  This also allows
documentation parsing and generation for multiple instances, but the rdoc
command-line tool does not support this.&lt;/p&gt;

&lt;p&gt;Due to this change RDoc::RDoc.current and RDoc::RDoc.reset no longer exist.&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Minor enhancements&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;Added &#8211;root for building documentation from outside the source dir.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Added a table of contents to the sidebar.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc markup format merges adjacent labels in a label or note list into a
single definition list item for output.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc now tracks use of extend.  Pull request #118 by Michael Granger.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc now tracks methods that use super.  Pull request #116 by Erik
Hollensbe.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Added methods ::system_dir, ::site_dir, ::home_dir and ::gem_dir to fetch
the components of RDoc::RI::Paths.path individually.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Added support for rb_file_const.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc now processes files in sorted order.  Issue #71 by V&#237;t Ondruch&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc now warns with &#8211;verbose when methods are duplicated.  Issue #71 by V&#237;t
Ondruch&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;ri will display documentation for all methods in a class if -a is given.
Issue #57 by casper&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;The RDoc coverage report will report line information for attributes,
constants and methods missing documentation.  Issue #121 by Zachary Scott&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc now reports a warning for files that are unreadable due to permissions
problems.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc controls documentation generation for RubyGems 2.0+&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Bug fixes&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;A word that is directly followed by a multi-word tidy link label no longer
disappears.  (Like &lt;code&gt;text{link}[http://example]&lt;/code&gt;)&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed legacy template support.  Pull Request #107 by Justin Baker.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;An HTML class in a verbatim section no longer triggers ruby parsing. Issue
#92 by Vijay Dev&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Improved documentation for setting the default documentation format for
your ruby project.  Issue #94 by Henrik Hodne&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed handling of LANG in the RDoc::Options tests.  Issue #99 by V&#237;t
Ondruch&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc no longer quits when given an entry that is not a file or directory.
Issue #101 by Charles Nutter&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed bug in syntax-highlighting that would corrupt regular expressions.
Ruby Bug #6488 by Benny Lyne Amorsen.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;&#8220;class Object&#8221; no longer appears in the coverage report if all its methods
are documented.  This suppresses a false positive for libraries that add
toplevel methods.  Pull Request #128 by Zachary Scott.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed test_gen_url test name in TestRDocMarkupToHtml.  Pull Request #130 by
Zachary Scott.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Comment-defined methods ahead of define_method are now discovered.  Issue
#133 by eclectic923&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed detection of define_method documentation.  Issue #138 by Marvin
G&#252;lker.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed lexing of character syntax (&lt;code&gt;?z&lt;/code&gt;).  Reported by Xavier
Noria.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Add license to gem spec.  Issue #144 by pivotalcommon&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed comment selection for classes.  Pull request #146 by pioz&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed parsing of &lt;code&gt;def self.&amp;amp;() end&lt;/code&gt;.  Issue #148 by Michael
Lucy&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Generated RD parser files are now included in the gem.  Issue #145 by
Marvin G&#252;lker&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Class and module aliases now create new classes to avoid duplicate names in
the class list.  Issue #143 by Richard Schneeman, Rails Issue #2839&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc::Markup::Parser now correctly matches indentation of lists when
multibyte characters are used in the list labels.  Issue #140 by
burningTyger&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed mangling of email addresses that look like labels.  Issue #129 by
Tobias Koch&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Classes and modules in a C file may now be created in any order.  Issue
#124 by Su Zhang&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;A metaprogrammed method supports the :args: directive.  Issue #100&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;A metaprogrammed method supports the :yields: directive.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc will now look for directives up to the end of the line.  For example,&lt;/p&gt;

&lt;pre class=&quot;ruby&quot;&gt;&lt;span class=&quot;ruby-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;ruby-constant&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;ruby-operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;ruby-constant&quot;&gt;A&lt;/span&gt;; &lt;span class=&quot;ruby-keyword&quot;&gt;end&lt;/span&gt; &lt;span class=&quot;ruby-comment&quot;&gt;# :nodoc:&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;will now hide documentation of B.  Issue #125 by Zachary Scott&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed tokenization of % when it is not followed by a $-string type&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed display of __END__ in documentation examples in HTML output&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed tokenization of reserved words used as new-style hash keys&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;RDoc now handles class &amp;lt;&amp;lt; $gvar by ignoring the body&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;dl class=&quot;rdoc-list note-list&quot;&gt;&lt;dt&gt;Fixed parsing of class A
&lt;dd&gt;
&lt;p&gt;B.&lt;/p&gt;
&lt;/dd&gt;&lt;/dl&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Worked around bug in RDoc::RubyLex where tokens won&amp;#39;t be reinterpreted
after unget_tk.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed class &amp;lt;&amp;lt; ::Foo writing documentation to /Foo.html&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed class ::A referencing itself from inside its own namespace.&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;/ul&gt;


</content>
  </entry>
  <entry>
    <id>tag:blog.segment7.net,2005:Article/1341</id>
    <published>2012-07-10T12:52:18-07:00</published>
    <updated>2012-07-10T12:52:18-07:00</updated>
    <link type="text/html" rel="alternate" href="http://blog.segment7.net/2012/07/10/streaming-zlib-processing-for-ruby"/>
    <author>
      <name>drbrain</name>
    </author>
    <title type="html">Streaming zlib processing for Ruby</title>
    <category label="Ruby" term="ruby" scheme="http://blog.segment7.net/category/ruby"/>
    <content type="html">&lt;p&gt;Earlier today I checked in a patch that adds streaming zlib processing to Ruby.  This allows you to process a stream without needing to allocate space to hold the entire result.  To add the streaming support I changed #inflate and #deflate to accept a block.  A handful of other methods (such as #finish) accept a block as well due to the internals of Zlib.  Here's an example:

&lt;pre&gt;&lt;code&gt;require 'zlib'

# dd if=/dev/zero of=/dev/stdout bs=1m count=1024 | gzip -c &gt; 1G.gz
gzipped = File.read '1G.gz'

# auto-detect gzip
z = Zlib::Inflate.new Zlib::MAX_WBITS + 32

# This prints NULs
z.inflate gzipped do |chunk|
  puts chunk
end

# Don't forget to finish the stream, there may be bytes leftover.
puts z.finish&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If the input was a zlib stream instead of a gzip stream, this would work:

&lt;code&gt;&lt;pre&gt;Zlib.inflate deflated do |chunk|
  puts chunk
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But Zlib.inflate doesn't allow specification of window bits for gzip auto-detection.

&lt;p&gt;The biggest difference is in memory used.  Here's 1GB of gzip-compressed NULs:

&lt;pre&gt;&lt;samp&gt;$ ll 1G.gz
-rw-r--r--  1 drbrain  staff  1042069 Jul  9 17:09 1G.gz&lt;/samp&gt;&lt;/pre&gt;

&lt;p&gt;Here's the memory used inflating this stream:

&lt;pre&gt;&lt;samp&gt;$ /usr/bin/time -l make -s runruby &gt; /dev/null
        3.56 real         3.25 user         0.29 sys
  46682112  maximum resident set size
         0  average shared memory size
         0  average unshared data size
         0  average unshared stack size
     12644  page reclaims
         0  page faults
         0  swaps
         0  block input operations
         0  block output operations
         0  messages sent
         0  messages received
         1  signals received
         3  voluntary context switches
        14  involuntary context switches&lt;/pre&gt;&lt;/samp&gt;

&lt;p&gt;Only 46MB used!

&lt;p&gt;Here's without streaming:

&lt;pre&gt;&lt;samp&gt;$ /usr/bin/time -l make -s runruby &gt; /dev/null
        3.82 real         3.21 user         0.60 sys
1079824384  maximum resident set size
         0  average shared memory size
         0  average unshared data size
         0  average unshared stack size
    264889  page reclaims
         0  page faults
         0  swaps
         0  block input operations
         0  block output operations
         0  messages sent
         0  messages received
         1  signals received
         3  voluntary context switches
        18  involuntary context switches&lt;/pre&gt;&lt;/samp&gt;

&lt;p&gt;Over 1GB used!

&lt;p&gt;As you may have noticed, despite all the extra calls back to ruby to execute the block, the streaming output was 250ms faster, but &lt;a href=&quot;http://blog.segment7.net/2012/06/27/verifying-benchmarks-with-ministat&quot;&gt;does that hold up&lt;/a&gt;?

&lt;h3&gt;Benchmarks&lt;/h3&gt;

&lt;p&gt;For all these benchmarks I chose files of NULs as the inflate to large files as this exercises the growth of the output buffer the most, which is what this new feature changes.  In general, these benchmarks show that in single-thread use streaming improves inflate speed especially as the output size increases while in multi-thread use streaming reduces inflate speed unless the output size grows very large.

&lt;p&gt;I chose the input sizes of 10KB, 100KB and 1GB as tests of the internals of the zlib extension.  At 10KB buffer expansion will only happen once for streaming mode, but several times for non-streaming.  100KB is in the realm of compressed HTTP responses and has a reasonable balance between the way streaming and non-streaming work are handled.  1GB is extremely large and when multi-threaded would be taxing on my laptop's memory capacity for non-streaming and taxing on the GVL while streaming.

&lt;p&gt;Using files that are less compressible would be a better real-world example and may change the speedups shown.  For single-thread tests, the speedup would likely increase while for multi-thread tests the slowdown would likely decrease.

&lt;p&gt;With a 1GB file of NULs, ministat shows a 6% speedup:

&lt;pre&gt;&lt;samp&gt;x stream
+ no-stream
+------------------------------------------------------------------------------+
|                                                                   +          |
|                                                                   +          |
|                                                                   ++         |
|                                                                 ++++         |
|              x                                                 +++++         |
|         x  xxx                                                +++++++        |
|  x x xxxx  xxx x                                              +++++++        |
|  x xxxxxxx xxxxx          x                                  ++++++++   +    |
|x x xxxxxxx xxxxxx  x      x   x       x     x            x   ++++++++++ +++ +|
|  |_________MA__________|                                                     |
|                                                                |__A__|       |
+------------------------------------------------------------------------------+
    N           Min           Max        Median           Avg        Stddev
x  50     3.4484119      3.690871      3.497622     3.5034132   0.045816556
+  50     3.7066622     3.7709568     3.7281418     3.7290156   0.013754228
Difference at 95.0% confidence
	0.225602 +/- 0.013422
	6.4395% +/- 0.383111%
	(Student's t, pooled s = 0.0338255)&lt;/samp&gt;&lt;/pre&gt;

&lt;p&gt;I believe this is due to the non-streaming execution needing to realloc() the output buffer during expansion.  The streaming version yields the buffer to the block and creates a new buffer which avoids the realloc() overhead for large strings.

&lt;p&gt;For 100KB of NULs inflated 100 times, no speedup is shown:

&lt;pre&gt;&lt;samp&gt;x stream
+ no-stream
+------------------------------------------------------------------------------+
|     +   xxxxx                                                                |
|    +++ +xxxxx                                                                |
|    +++++*xxxxx x                                                             |
|  +++++++*xxxxxxx                  + +  +                +                    |
|+ +++++++**xxxxx* * xxx   +       +*++ ++   +  + +       ++ +  x    x     +  +|
|    |_______M__A__________|                                                   |
||________M____________A____________________|                                  |
+------------------------------------------------------------------------------+
    N           Min           Max        Median           Avg        Stddev
x  50   0.036626816   0.045912027   0.037170887   0.037605586  0.0017813789
+  50   0.035252094   0.047364235   0.036613226   0.038649669  0.0033843024
No difference proven at 95.0% confidence&lt;/samp&gt;&lt;/pre&gt;

&lt;p&gt;At 10KB of NULs inflated 1000 times each run, the improvement drops to 6%:

&lt;pre&gt;&lt;samp&gt;x stream
+ no-stream
+------------------------------------------------------------------------------+
|              ++                                                              |
|    xxx       ++                                                              |
|    xxx       +++                                                             |
|    xxx       +++                                                             |
|   xxxx x     +++                                                             |
|   xxxx x    ++++                                                             |
|   xxxx x    ++++                                                             |
|   xxxxxx    ++++ +                                                           |
|  xxxxxxx   +*+++++  +                                                        |
|  xxxxxxxx  **++++++ ++  *                + +  *   +                         +|
||____M_A______|                                                               |
|       |_______M___A___________|                                              |
+------------------------------------------------------------------------------+
    N           Min           Max        Median           Avg        Stddev
x  50   0.046477079    0.05746603   0.047408819   0.047745066  0.0016545295
+  50   0.049071074   0.064721823   0.049803019   0.050768676   0.002927008
Difference at 95.0% confidence
	0.00302361 +/- 0.000943385
	6.33282% +/- 1.97588%
	(Student's t, pooled s = 0.00237748)&lt;/samp&gt;&lt;/pre&gt;

&lt;p&gt;In this case the improvement is likely due to the way the buffer is expanded.  Streaming mode jumps from the initial buffer size (1KB) to the maximum buffer size (16KB) immediately while non-streaming mode increments the buffer in steps.  I'll need further performance tests to see if eliminating stepping output buffer growth is worthwhile for both modes.

&lt;p&gt;When multiple zlib streams are being processed in parallel streaming is 20% slower when expanding a 10KB streams of NULs 1000 times in four threads:

&lt;pre&gt;&lt;samp&gt;x stream
+ no-stream
+------------------------------------------------------------------------------+
|              +                                         xx                    |
|           +  +                                       x xx                    |
|           ++ +                                       x xx                    |
|          +++ +                                       x xx x                  |
|          ++++++                                      x xx x                  |
|        ++++++++                                     xxxxx x x                |
|   +    ++++++++ +                                   xxxxxxx x x              |
|++ +  + ++++++++ ++    +         +                  xxxxxxxxxxxx xxx  x      x|
|                                                     |___MA____|              |
|       |____A____|                                                            |
+------------------------------------------------------------------------------+
    N           Min           Max        Median           Avg        Stddev
x  50    0.19220901    0.21440268    0.19658995     0.1977196  0.0041590721
+  50    0.14678812    0.17618799    0.15705991    0.15724883  0.0045392638
Difference at 95.0% confidence
	-0.0404708 +/- 0.0017274
	-20.4688% +/- 0.87366%
	(Student's t, pooled s = 0.00435332)&lt;/samp&gt;&lt;/pre&gt;

&lt;p&gt;With 100KB of NULs expanded 100 times in four threads there's a 14% slowdown:

&lt;pre&gt;&lt;samp&gt;x stream
+ no-stream
+------------------------------------------------------------------------------+
|        + +++ +                                      xxxx x                   |
|        + +++ +                                      xxxxxx  x                |
| + ++ +++++++ ++  +    +                   +       xxxxxxxx  x +            x |
|++ ++++++++++ ++  +  + +   + +++          ++    xxxxxxxxxxxxxx *xxx   x    xxx|
|                                                   |____M_A______|            |
|  |________M____A_____________|                                               |
+------------------------------------------------------------------------------+
    N           Min           Max        Median           Avg        Stddev
x  50   0.069380999   0.076375008   0.071210146   0.071699142  0.0016866267
+  50   0.057549715   0.073060989   0.060353994   0.061419401  0.0034865206
Difference at 95.0% confidence
	-0.0102797 +/- 0.0010867
	-14.3373% +/- 1.51564%
	(Student's t, pooled s = 0.00273866)&lt;/samp&gt;&lt;/pre&gt;

&lt;p&gt;These slowdowns are likely due to increased GVL contention.  As the output size grows the slowdown decreases.

&lt;p&gt;With 1G of NULs expanded once in four thread's there's a 1% speedup:

&lt;pre&gt;&lt;samp&gt;x stream
+ no-stream
+------------------------------------------------------------------------------+
|    x x +                                                                     |
|    x x++x++                                                                  |
|    x ***x++                                                                  |
|    xx******                                                                  |
|    xx******                                                                  |
|  xx********+++                                                               |
|  x**********++   +x  x +   +                 +                              +|
|    |__A___|                                                                  |
||________M__A__________|                                                      |
+------------------------------------------------------------------------------+
    N           Min           Max        Median           Avg        Stddev
x  50     5.1492789     5.3822649     5.2116029     5.2147137   0.043439149
+  50     5.1704421     6.0051818     5.2339363     5.2634319     0.1322479
Difference at 95.0% confidence
	0.0487181 +/- 0.0390566
	0.934244% +/- 0.748968%
	(Student's t, pooled s = 0.0984288)&lt;/samp&gt;&lt;/pre&gt;

&lt;p&gt;The speedup is due to realloc() needing to copy the string multiple times.


</content>
  </entry>
  <entry>
    <id>tag:blog.segment7.net,2005:Article/1340</id>
    <published>2012-06-27T16:48:50-07:00</published>
    <updated>2012-06-28T13:22:18-07:00</updated>
    <link type="text/html" rel="alternate" href="http://blog.segment7.net/2012/06/27/verifying-benchmarks-with-ministat"/>
    <author>
      <name>drbrain</name>
    </author>
    <title type="html">Verifying benchmarks with ministat</title>
    <category label="Ruby" term="ruby" scheme="http://blog.segment7.net/category/ruby"/>
    <category label="Testing" term="testing" scheme="http://blog.segment7.net/category/testing"/>
    <content type="html">&lt;p&gt;Most people know to benchmark to verify performance improvements, but comparing a handful of results isn't enough.  You need to be sure your results are statistically significant.  &lt;a href=&quot;http://www.freebsd.org/cgi/man.cgi?query=ministat&quot;&gt;ministat&lt;/a&gt; is a tool written by &lt;a href=&quot;http://phk.freebsd.dk/index.html&quot;&gt;Poul-Henning Kamp&lt;/a&gt; that determines if two result sets are statistically significant and display the difference in performance between the two.

&lt;p&gt;I recently used ministat to measure performance changes for my &lt;a href=&quot;https://bugs.ruby-lang.org/issues/6615&quot;&gt;GVL release patch&lt;/a&gt; for Ruby's Zlib extension.  The patch will allow multiple zlib or gzip streams to be deflated or inflated in parallel.  I was asked to show any performance difference because the GVL release/acquire can be expensive depending upon the work done without the GVL.

&lt;p&gt;I &lt;a href=&quot;http://youtube.com/watch?v=uvidgwKyPh4#t=41&quot;&gt;posted a video&lt;/a&gt; showing the difference between inflating very large files, but what about single-threaded use of Zlib? What about the worst case?  While parallel processing of large streams is great, it shouldn't overly penalize single-thread or small-stream processing.  I ran several benchmarks of single-threaded use to show minimal difference, but in the worst-case benchmarks I couldn't be sure there was any significant performance change.

&lt;h3&gt;Zlib background&lt;/h3&gt;

&lt;p&gt;For simplicity I'll only be mentioning inflate from here on, but the same loop handles inflate and deflate of gzip, zlib and raw deflate streams identically.

&lt;p&gt;While the Zlib extension is written in C, I've written this in roughly equivalent ruby while hand-waving over some of the details of how libz works since they're unimportant to the performance comparison.  Before my patch run loop looked like this:

&lt;pre&gt;&lt;code&gt;setup_input_buffer stream
setup_output_buffer stream

loop do
  status = inflate stream

  schedule_another_thread

  return output_buffer if status == STREAM_END

  if status == BUF_ERROR then
    expand_output_buffer stream
    next
  else
    # handle other errors
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First the input and output buffers are set up.  The input buffer contains the deflated string to be inflated and the output buffer will contain the inflated string.  The default output buffer size is 1024 bytes.

&lt;p&gt;Inside the loop inflate is called which will expand as much of the input stream as will fit in the output buffer, then ruby is given the chance to schedule another thread to provide fairness, then errors are checked.

&lt;p&gt;A &lt;code&gt;BUF_ERROR&lt;/code&gt; indicates there isn't enough room in the output buffer and more space needs to be added.  The expand_output_buffer function adds up to another 16KB to the output buffer.  Combined with scheduling another thread each time inflate returned, fairness is provided.

&lt;p&gt;With my patch the run loop looks something like this:

&lt;pre&gt;&lt;code&gt;setup_input_buffer stream
setup_output_buffer stream

release_GVL do
  until interrupted do
    status = inflate stream

    return output_buffer if status == STREAM_END

    if status == BUF_ERROR then
      expand_output_buffer_without_GVL stream
      next
    else
      # &amp;#8230;
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The differences are releasing the GVL, the interrupted flag and the change in expanding the output buffer.

&lt;p&gt;To reduce copying the Zlib extension uses a ruby String for the output buffer, so expanding it requires GC interaction.  The new function uses &lt;code&gt;realloc(3)&lt;/code&gt; directly to avoid GVL contention and mirrors &lt;code&gt;rb_str_resize()&lt;/code&gt;.

&lt;p&gt;The interrupted flag allows processing of timeouts, a killed thread or clean shutdown to proceed smoothly.  Like the no-GVL version the buffer is only expanded by 16KB to allow interruptions to be serviced quickly.  Without this flag a large stream would need to complete before the thread it is running in could be shut down which may take several seconds.  (In the C version of release_GVL, &lt;code&gt;rb_thread_blocking_region()&lt;/code&gt;, you provide an unblocking function that sets the interrupted flag when ruby wants to regain control of the thread.)

&lt;p&gt;Releasing the GVL allow other threads to run the Ruby VM so while a stream is being inflated other threads can run on other CPUs.  For large streams this can result in a performance increase when other Ruby threads are running.

&lt;h3&gt;Worst Case Benchmark&lt;/h3&gt;

&lt;p&gt;After inspecting the two implementations we have enough information to create a worst-case scenario for testing the performance of the patch.

&lt;p&gt;Since GVL release/acquire can be expensive we want to do that as much as possible which means inflate should do as little as possible.  The buffer should not be expanded since that allows more than one trip through inflate() per GVL release/acquire, so inflated strings must fit in the 1024 byte output buffer.

&lt;p&gt;I wrote a benchmark that inflates many strings with an inflated size of 1000 bytes using multiple threads, but not so many strings as to prevent a quick return from the benchmark section.  (While inflating strings of zero bytes would probably be worse, that seems unrealistic.)

&lt;p&gt;Here's the benchmark program I wrote:

&lt;code&gt;&lt;pre&gt;require 'zlib'
require 'benchmark'

r = Random.new 0

file_count = 10_000

deflated = (0..file_count).map do
  input = r.bytes 1000
  Zlib::Deflate.deflate input
end

times = Benchmark.measure do
  (0..3).map do
    Thread.new do
      deflated.each do |input|
        Zlib::Inflate.inflate input
      end
    end
  end.each do |t|
    t.join
  end
end

puts times.real&lt;/pre&gt;&lt;/code&gt;

&lt;p&gt;Instead of using &lt;kbd&gt;time&lt;/kbd&gt;, &lt;code&gt;Benchmark.measure&lt;/code&gt; is used, but only around the inflate part.  This reduces the amount of noise in the benchmark.  By choosing only 10,000 files multiple benchmarks can be run (on my machine the inflate portion takes a little over &amp;#189; second).  By using the same random seed the benchmark is repeatable.

&lt;p&gt;Before using ministat I ran the same benchmark but with 100,000 files I had the following results without the patch:

&lt;pre&gt;&lt;samp&gt;$ for f in `jot 5`; do ruby20 test.rb; done
5.420000   5.970000  11.390000 (  8.162893)
5.400000   6.270000  11.670000 (  8.263046)
5.460000   5.920000  11.380000 (  8.133742)
5.410000   6.290000  11.700000 (  8.289913)
5.500000   6.620000  12.120000 (  8.478085)&lt;/samp&gt;&lt;/pre&gt;

&lt;p&gt;and with the patch:

&lt;pre&gt;&lt;samp&gt;$ for f in `jot 5`; do make -s runruby; done
5.120000   6.240000  11.360000 (  8.039715)
5.240000   6.260000  11.500000 (  8.097961)
5.280000   5.940000  11.220000 (  8.004246)
5.210000   6.360000  11.570000 (  8.171124)
5.240000   6.200000  11.440000 (  8.054929)&lt;/samp&gt;&lt;/pre&gt;

&lt;p&gt;So while running with the patch seemed faster, the results overlap by a small margin.  I wanted to be reasonably sure there was an improvement which is where ministat comes in.  In order to get useful data out of ministat I would need more data (this is easy to verify by running ministat on these results and seeing that it says &quot;No difference&quot;).

&lt;p&gt;To capture the data I used a shell for loop to run the benchmark 50 times and redirect the output to a file: &lt;kbd&gt;for f in `jot 50`; do make -s runruby; done &gt; with&lt;/kbd&gt;, and again without the patch applied directed to a &quot;without&quot; file.

&lt;h3&gt;ministat&lt;/h3&gt;

&lt;p&gt;To determine if the results were statistically significant I ran the data through ministat with a confidence interval of 99%.  From the &lt;cite&gt;ministat man page&lt;/cite&gt;:

&lt;blockquote cite=&quot;http://www.freebsd.org/cgi/man.cgi?query=ministat&quot;&gt;
&lt;p&gt;The ministat command was written by Poul-Henning Kamp out of frustration over all the bogus benchmark claims made by people with no understanding of the importance of uncertainty and statistics.
&lt;/blockquote&gt;

&lt;p&gt;So through ministat we will be able to determine if the suspected difference from the previous benchmark is an actual difference, and what the certainty of that difference is.

&lt;pre&gt;&lt;samp&gt;$ ministat -c 99 -s without with
x without
+ with
+------------------------------------------------------------------------------+
|                           +     + +  x    *  xx      x                       |
|         +     x +   +     +  +  + +  x   **+xx*xx    x * x +               x |
|+        ++++  x + x*+ * + ++x+x++x*++x* ***+x**xx * +x**** * + x   x       xx|
|                                |_____________A_____________|                 |
|                    |______________A_______________|                          |
+------------------------------------------------------------------------------+
    N           Min           Max        Median           Avg        Stddev
x  50    0.61660767    0.71641994    0.66669798    0.66647618   0.022548872
+  50    0.59242272    0.69294882    0.64941692    0.64917859    0.02509235
Difference at 99.0% confidence
	-0.0172976 +/- 0.0125332
	-2.59538% +/- 1.88051%
	(Student's t, pooled s = 0.0238545)&lt;/samp&gt;&lt;/pre&gt;

&lt;p&gt;Looking at the last four lines, you can see there is a statistically significant difference in the benchmark results at 99% confidence.  Running the benchmark with the patch shows a 17ms decrease in time &amp;plusmn; 13ms or a 2.6% decrease in time &amp;plusmn; 1.9% for this sample set, so I can say &quot;minor improvement&quot;.

&lt;p&gt;The box shows a plot of the with and without values along with the average (and median) values, and standard deviation bars.  For full details see the &lt;a href=&quot;http://www.freebsd.org/cgi/man.cgi?query=ministat&quot;&gt;ministat man page&lt;/a&gt;.

&lt;p&gt;There are a couple of likely reasons for the slight increase in performance such as the GVL release/acquire being inexpensive enough that inflate takes longer allowing parallelism or that GVL release/acquire isn't as expensive as thought, but without an easy way to measure GVL contention it's only speculation.

&lt;h3&gt;Getting ministat&lt;/h3&gt;

&lt;p&gt;To my knowledge ministat only ships with FreeBSD, but fortunately it is really easy to add to nearly any system with a C compiler.  You can find a copy of ministat in &lt;a href=&quot;https://github.com/codahale/ministat&quot;&gt;this repository&lt;/a&gt; (which, ironically, &lt;a href=&quot;https://www.varnish-cache.org/docs/2.1/phk/autocrap.html&quot;&gt;uses autotools&lt;/a&gt;) or you can &lt;a href=&quot;https://raw.github.com/codahale/ministat/master/src/ministat.c&quot;&gt;grab the C file directly&lt;/a&gt; and run &lt;kbd&gt;cc ministat.c -lm -o ministat&lt;/kbd&gt; and move the ministat executable into your PATH like I did.

</content>
  </entry>
  <entry>
    <id>tag:blog.segment7.net,2005:Article/1339</id>
    <published>2012-05-09T13:48:00-07:00</published>
    <updated>2012-05-09T13:48:00-07:00</updated>
    <link type="text/html" rel="alternate" href="http://blog.segment7.net/2012/05/09/mechanize-2-5"/>
    <author>
      <name>drbrain</name>
    </author>
    <title type="html">Mechanize 2.5</title>
    <category label="Software" term="software" scheme="http://blog.segment7.net/category/software"/>
    <content type="html">&lt;ul&gt;&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://mechanize.rubyforge.org&quot;&gt;Documentation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;&lt;a
href=&quot;https://github.com/tenderlove/mechanize&quot;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The Mechanize library is used for automating interaction with websites.
Mechanize automatically stores and sends cookies, follows redirects, and
can follow links and submit forms.  Form fields can be populated and
submitted.  Mechanize also keeps track of the sites that you have visited
as a history.&lt;/p&gt;

&lt;h3 id=&quot;label-Changes&quot;&gt;Changes&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;Minor enhancement&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;Added Mechanize#ignore_bad_chunking for working around servers that don&amp;rsquo;t
terminate chunked transfer-encoding properly.  Enabling this may cause data
loss.  Issue #116&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Removed content-type check from Mechanize::Page allowing forced parsing of
incorrect or missing content-types.  Issue #221 by GarthSnyder&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Bug fixes&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;Fixed typos in EXAMPLES and GUIDES.  Pull Request #213 by Erkan Yilmaz.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed handling of a quoted content-disposition size.  Pull Request #220 by
Jason Rust&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Mechanize now ignores a missing gzip footer like browsers do.  Issue #224
by afhbl&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Mechanize handles saving of files with the same name better now.  Pull
Request #223 by Godfrey Chan, Issue #219 by Jon Hart&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Mechanize now sends headers across redirects.  Issue #215 by Chris Gahan&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Mechanize now raises Mechanize::ResponseReadError when the server does not
terminate chunked transfer-encoding properly.  Issue #116&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Mechanize no longer raises an exception when multiple identical
radiobuttons are checked.  Issue #214 by Matthias Guenther&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Fixed documentation for pre_connect_hooks and post_connect_hooks.  Issue
#226 by Robert Poor&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Worked around ruby 1.8 run with -Ku and ISO-8859-1 encoded characters in
URIs.  Issue #228 by Stanislav O.Pogrebnyak&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;/ul&gt;


</content>
  </entry>
  <entry>
    <id>tag:blog.segment7.net,2005:Article/1338</id>
    <published>2012-05-03T17:57:28-07:00</published>
    <updated>2012-05-03T17:57:28-07:00</updated>
    <link type="text/html" rel="alternate" href="http://blog.segment7.net/2012/05/03/mechanics-of-programming"/>
    <author>
      <name>drbrain</name>
    </author>
    <title type="html">Mechanics of Programming</title>
    <category label="Misc" term="misc" scheme="http://blog.segment7.net/category/misc"/>
    <content type="html">&lt;p&gt;I sat down with &lt;a href=&quot;http://eliseworthy.com/&quot;&gt;Elise Worthy&lt;/a&gt; at &lt;a href=&quot;http://railsconf2012.com/&quot;&gt;RailsConf&lt;/a&gt; to pair with her on a Rails application that used the &lt;a href=&quot;http://www.wunderground.com/weather/api/&quot;&gt;Wunderground API&lt;/a&gt; to retrieve the weather for multiple cities.  If you don't know Elise, she's a &lt;a href=&quot;http://hungryacademy.com/&quot;&gt;Hungry Academy&lt;/a&gt; student formerly of Seattle.  You can read about &lt;a href=&quot;http://blog.hungryacademy.com/blog/2012/05/03/personal-weather/&quot;&gt;how she built her app&lt;/a&gt; on the &lt;a href=&quot;http://blog.hungryacademy.com/&quot;&gt;Hungry Academy Blog&lt;/a&gt;.  Since Elise is new to programming, pairing with her made me think about how I work on small tasks when implementing a larger feature.

&lt;p&gt;When I first sat down, Elise had a class to retrieve the weather for Washington D.C., a controller and a view to display it.  Our task was to add a search box so you could show the weather for any ZIP code in addition to Washington D.C.

&lt;p&gt;By implementing weather for a fixed city first Elise had followed the most difficult lesson for me to learn, only implement one idea, or story, at a time.  When I try to add too much I can't fit all the details in my head.  By making the weather work for one fixed city she had a solid base of work she could revert to to try again if she got stuck.

&lt;p&gt;I mostly helped her with the question of &quot;what should I do next?&quot;  Elise knew which steps she needed to perform but didn't know what the best order was.  I've found that working on the easiest task first is best.  By picking the easiest task you have time to think about the hard tasks in the back of your mind.  By the time you get around to them you may have made them easier or you may have come up with an easier way to implement them.

&lt;p&gt;In the course of doing the easiest thing next we switched back and forth between the API wrapper, the controller and the view.  Each change we made was very small.  For example, first add the search form, next extract the ZIP code from &lt;code&gt;params&lt;/code&gt;, then replace showing Washington D.C. with the user's choice.

&lt;p&gt;Each step only changed a couple lines that we verified in the browser so we didn't get ahead of ourselves.  By first changing from a fixed city to an arbitrary city we advanced towards our goal without confusing ourselves with extra details.  While this broke one feature of the app, it was obvious that it would be easy to restore in the future when we were ready to address it.

&lt;p&gt;I also find it useful to add &lt;code&gt;TODO&lt;/code&gt; comments when I know I need to change or fix something but don't want to do it yet.  The &lt;code&gt;TODO&lt;/code&gt; item may be a distraction at this time or something difficult that a future step will make easier.  I find it easy to forget some necessary cleanup without them.  We added a few when Elise would think of something she needed to change but I didn't want to get us distracted.

&lt;p&gt;There was one other tip I had for Elise, as she was adding support for both Washington D.C. and the user's ZIP her first idea was to use two instance variables to provide the data to the view, one for Washington D.C. and the other for the user's city.  She also asked if I thought this was the best way.

&lt;p&gt;I told her that it is easier for me to think of handling just one item or handling many items, but not just two items.  By having only these two categories of items to display it makes it easier to maintain your code by preventing duplication.

&lt;p&gt;The best thing that came out of pairing with Elise was that I got to think about how I program at the lowest level.  While I got to show Elise some tips I've learned over the years, she showed me the details of my own internal process that I barely think about anymore.

</content>
  </entry>
  <entry>
    <id>tag:blog.segment7.net,2005:Article/1337</id>
    <published>2012-04-20T17:53:57-07:00</published>
    <updated>2012-04-20T17:53:57-07:00</updated>
    <link type="text/html" rel="alternate" href="http://blog.segment7.net/2012/04/20/mechanize-2-4-security-fix"/>
    <author>
      <name>drbrain</name>
    </author>
    <title type="html">Mechanize 2.4 Security Fix</title>
    <category label="Software" term="software" scheme="http://blog.segment7.net/category/software"/>
    <content type="html">&lt;ul&gt;&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://mechanize.rubyforge.org&quot;&gt;mechanize.rubyforge.org&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;&lt;a
href=&quot;https://github.com/tenderlove/mechanize&quot;&gt;github.com/tenderlove/mechanize&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The Mechanize library is used for automating interaction with websites.
Mechanize automatically stores and sends cookies, follows redirects, and
can follow links and submit forms.  Form fields can be populated and
submitted.  Mechanize also keeps track of the sites that you have visited
as a history.&lt;/p&gt;

&lt;h3 id=&quot;label-Changes&quot;&gt;Changes&lt;/h3&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;Security fix:&lt;/p&gt;

&lt;p&gt;Mechanize#auth and Mechanize#basic_auth allowed disclosure of passwords to
malicious servers and have been deprecated.&lt;/p&gt;

&lt;p&gt;In prior versions of mechanize only one set of HTTP authentication
credentials were allowed for all connections.  If a mechanize instance
connected to more than one server then a malicious server detecting
mechanize could ask for HTTP Basic authentication.  This would expose the
username and password intended only for one server.&lt;/p&gt;

&lt;p&gt;Mechanize#auth and Mechanize#basic_auth now warn when used.&lt;/p&gt;

&lt;p&gt;To fix the warning switch to &lt;a href=&quot;http://mechanize.rubyforge.org/Mechanize.html#method-i-add_auth&quot;&gt;Mechanize#add_auth&lt;/a&gt; which requires the URI
the credentials are intended for, the username and the password. Optionally
an HTTP authentication realm or NTLM domain may be provided.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p&gt;Minor enhancement&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;
&lt;p&gt;Improved exception messages for 401 Unauthorized responses.  Mechanize now
tells you if you were missing credentials, had an incorrect password, etc.&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;/ul&gt;


</content>
  </entry>
</feed>
