<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Julia Community 🟣: Neven</title>
    <description>The latest articles on Julia Community 🟣 by Neven (@nsajko).</description>
    <link>https://forem.julialang.org/nsajko</link>
    <image>
      <url>https://forem.julialang.org/images/7nCStKq1NkGSxn2JiN-9e_PQt7mIKfrIaI0AatVP5MA/rs:fill:90:90/g:sm/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L3VzZXIvcHJvZmls/ZV9pbWFnZS85MjIv/Y2VlZjU0YzAtZjJi/NC00ODA0LWEwYmQt/NmU5MDZiMTdhNTdh/LmpwZWc</url>
      <title>Julia Community 🟣: Neven</title>
      <link>https://forem.julialang.org/nsajko</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.julialang.org/feed/nsajko"/>
    <language>en</language>
    <item>
      <title>Profile a short-running function</title>
      <dc:creator>Neven</dc:creator>
      <pubDate>Mon, 02 Jun 2025 19:21:59 +0000</pubDate>
      <link>https://forem.julialang.org/nsajko/profile-a-short-running-function-5f8j</link>
      <guid>https://forem.julialang.org/nsajko/profile-a-short-running-function-5f8j</guid>
      <description>&lt;p&gt;Recently I went to profile a short-running function. Several Julia packages, ProfileCanvas.jl being one of them, provide functionality for getting a CPU execution profile, often via a macro called like &lt;code&gt;@profview expr_to_profile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One problem that can occur is the run time of one invocation of &lt;code&gt;expr_to_profile&lt;/code&gt; being so short that the profile ends up being useless because not enough samples are collected. Here's a quick-and-dirty hack solution to this problem. Criticize it in the comments below!&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: profiling &lt;code&gt;cos(::Float64)&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="s"&gt;"""
    run_in_a_loop(run_workload, get_argument, repeat_count)::Nothing
"""&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; run_in_a_loop&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_workload&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_argument&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repeat_count&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;G&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;∈&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;repeat_count&lt;/span&gt;
        &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_argument&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;@noinline&lt;/span&gt; &lt;span class="n"&gt;run_workload&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;donotdelete&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c"&gt;# Example: profile `cos(::Float64)` execution&lt;/span&gt;

&lt;span class="c"&gt;# Use a global to prevent constant folding, but precompute everything&lt;/span&gt;
&lt;span class="c"&gt;# to allow the intended workload to dominate the profiling results.&lt;/span&gt;
&lt;span class="n"&gt;precomputed_arguments&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;NTuple&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Float64&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="x"&gt;,);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; get_argument&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;axs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OneTo&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;precomputed_arguments&lt;/span&gt;&lt;span class="x"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mod&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;axs&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;precomputed_arguments&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c"&gt;# Use a global to prevent unexpected compiler optimization.&lt;/span&gt;
&lt;span class="n"&gt;repeat_count&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;ProfileCanvas&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nd"&gt;@profview&lt;/span&gt;

&lt;span class="c"&gt;# Get everything compiled. The profile may (?) include compilation&lt;/span&gt;
&lt;span class="c"&gt;# here, so we're not interested in it yet.&lt;/span&gt;
&lt;span class="n"&gt;run_in_a_loop&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_argument&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repeat_count&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@profview&lt;/span&gt; &lt;span class="n"&gt;run_in_a_loop&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_argument&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repeat_count&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Run again to see run-time performance.&lt;/span&gt;
&lt;span class="n"&gt;repeat_count&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="nd"&gt;@profview&lt;/span&gt; &lt;span class="n"&gt;run_in_a_loop&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_argument&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repeat_count&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the profile flame graph I ended up with:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://forem.julialang.org/images/9jNXKyQ-oJOOyWPZVE-vpjLoOg7Oi1apQu0T__I38lQ/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL3M1/bnVpbHIxb3ZsM3Fm/NGc0ejE3LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://forem.julialang.org/images/9jNXKyQ-oJOOyWPZVE-vpjLoOg7Oi1apQu0T__I38lQ/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9mb3Jl/bS5qdWxpYWxhbmcu/b3JnL3JlbW90ZWlt/YWdlcy91cGxvYWRz/L2FydGljbGVzL3M1/bnVpbHIxb3ZsM3Fm/NGc0ejE3LnBuZw" alt="profile flame graph for the example" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So about 85% of the samples do end up in &lt;code&gt;cos&lt;/code&gt;, even though a single call of &lt;code&gt;cos(::Float64)&lt;/code&gt; is over very quickly. Not bad!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;donotdelete&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The secret sauce above is &lt;code&gt;donotdelete&lt;/code&gt;. This is its doc string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;help?&amp;gt; Base.donotdelete
  │ Warning
  │
  │  The following bindings may be internal; they may change or be removed in future versions:
  │
  │    •  Base.donotdelete

  Base.donotdelete(args...)

  This function prevents dead-code elimination (DCE) of itself and any arguments passed to it, but is
  otherwise the lightest barrier possible. In particular, it is not a GC safepoint, does not model an
  observable heap effect, does not expand to any code itself and may be re-ordered with respect to
  other side effects (though the total number of executions may not change).

  A useful model for this function is that it hashes all memory reachable from args and escapes this
  information through some observable side-channel that does not otherwise impact program behavior. Of
  course that's just a model. The function does nothing and returns nothing.

  This is intended for use in benchmarks that want to guarantee that args are actually computed.
  (Otherwise DCE may see that the result of the benchmark is unused and delete the entire benchmark
  code).

  │ Note
  │
  │  donotdelete does not affect constant folding. For example, in donotdelete(1+1), no add
  │  instruction needs to be executed at runtime and the code is semantically equivalent to
  │  donotdelete(2).

  │ Note
  │
  │  This intrinsic does not affect the semantics of code that is dead because it is
  │  unreachable. For example, the body of the function f(x) = false &amp;amp;&amp;amp; donotdelete(x) may be
  │  deleted in its entirety. The semantics of this intrinsic only guarantee that if the
  │  intrinsic is semantically executed, then there is some program state at which the value of
  │  the arguments of this intrinsic were available (in a register, in memory, etc.).

  │ Julia 1.8
  │
  │  This method was added in Julia 1.8.

  Examples
  ≡≡≡≡≡≡≡≡

  function loop()
      for i = 1:1000
          # The compiler must guarantee that there are 1000 program points (in the correct
          # order) at which the value of `i` is in a register, but has otherwise
          # total control over the program.
          donotdelete(i)
      end
  end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar functionality in Rust:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://doc.rust-lang.org/beta/std/hint/fn.black_box.html" rel="noopener noreferrer"&gt;https://doc.rust-lang.org/beta/std/hint/fn.black_box.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some C++ libraries offer similar functionality, too. For example, the &lt;a href="https://github.com/facebook/folly" rel="noopener noreferrer"&gt;folly&lt;/a&gt; library has &lt;code&gt;doNotOptimizeAway&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;EDIT: &lt;code&gt;Base.donotdelete&lt;/code&gt; is now a public interface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/JuliaLang/julia/pull/55774" rel="noopener noreferrer"&gt;https://github.com/JuliaLang/julia/pull/55774&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Tuple transpose</title>
      <dc:creator>Neven</dc:creator>
      <pubDate>Sun, 18 Dec 2022 10:43:11 +0000</pubDate>
      <link>https://forem.julialang.org/nsajko/tuple-transpose-3k1</link>
      <guid>https://forem.julialang.org/nsajko/tuple-transpose-3k1</guid>
      <description>&lt;p&gt;Today I wrote a function and had some trouble figuring out what name should I give it, until realizing that it's a tuple transpose of sorts!&lt;/p&gt;

&lt;p&gt;This is the implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight julia"&gt;&lt;code&gt;&lt;span class="n"&gt;getindexer&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;let&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
    &lt;span class="n"&gt;coll&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;coll&lt;/span&gt;&lt;span class="x"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="x"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;transpose&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;NTuple&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="kt"&gt;NTuple&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;:&lt;/span&gt;&lt;span class="kt"&gt;Any&lt;/span&gt;&lt;span class="x"&gt;}})&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="x"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;ntuple&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tuple&lt;/span&gt;
      &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getindexer&lt;/span&gt;&lt;span class="x"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="x"&gt;),&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="x"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="x"&gt;,&lt;/span&gt; 
    &lt;span class="kt"&gt;Val&lt;/span&gt;&lt;span class="x"&gt;{&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="x"&gt;}())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When interpreting a tuple of equally-sized tuples as a matrix, the &lt;code&gt;transpose&lt;/code&gt; function returns the transpose of such a matrix.&lt;/p&gt;

&lt;p&gt;Here are two example inputs and outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;julia&amp;gt; matrix2x3 = ((1, 2, 3), (4, 5, 6))
((1, 2, 3), (4, 5, 6))

julia&amp;gt; matrix3x3 = ((:aa, :ab, :ac), (:ba, :bb, :bc), (:ca, :cb, :cc))
((:aa, :ab, :ac), (:ba, :bb, :bc), (:ca, :cb, :cc))

julia&amp;gt; transpose(matrix2x3)
((1, 4), (2, 5), (3, 6))

julia&amp;gt; transpose(matrix3x3)
((:aa, :ba, :ca), (:ab, :bb, :cb), (:ac, :bc, :cc))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The transpose is a self-inverse:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;julia&amp;gt; matrix2x3 == transpose(transpose(matrix2x3))
true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The implementation allows Julia to infer the return types as expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;julia&amp;gt; using Test

julia&amp;gt; matrix5x6 = ntuple(i -&amp;gt; ntuple(j -&amp;gt; i*100 + j, 6), 5)
((101, 102, 103, 104, 105, 106), (201, 202, 203, 204, 205, 206), (301, 302, 303, 304, 305, 306), (401, 402, 403, 404, 405, 406), (501, 502, 503, 504, 505, 506))

julia&amp;gt; @inferred transpose(matrix5x6)
((101, 201, 301, 401, 501), (102, 202, 302, 402, 502), (103, 203, 303, 403, 503), (104, 204, 304, 404, 504), (105, 205, 305, 405, 505), (106, 206, 306, 406, 506))

julia&amp;gt; @inferred transpose(transpose(matrix5x6))
((101, 102, 103, 104, 105, 106), (201, 202, 203, 204, 205, 206), (301, 302, 303, 304, 305, 306), (401, 402, 403, 404, 405, 406), (501, 502, 503, 504, 505, 506))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JET checks pass, too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;julia&amp;gt; using JET

julia&amp;gt; @report_opt transpose(matrix5x6)
No errors detected


julia&amp;gt; @report_opt transpose(transpose(matrix5x6))
No errors detected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>tuple</category>
      <category>matrix</category>
      <category>transpose</category>
      <category>adjoint</category>
    </item>
  </channel>
</rss>
