flame bait: execution speed Perl vs. C (Date::Calc::PP vs. Date::Calc::XS)

2009-11-18 Thread O. STeffen BEYer
Dear Module Authors,

recently in one of the Amsterdam Perl Mongers meetings the question came up
how much faster actually the XS version of Date::Calc (Date::Calc::XS) was
as compared to the Pure Perl version (Date::Calc::PP).

Here is the answer (see attached script - you will need to have Date::Calc
6.3 and Date::Calc::XS 6.2 installed to run this script successfully):

FreeBSD 7.2.-stable:

$ perl benchmark.pl
Running under Date::Calc::PP version 6.3
timethis 5000: 17.3147 wallclock secs (17.24 usr +  0.06 sys = 17.30 CPU) @
288.94/s (n=5000)
Running under Date::Calc::XS version 6.2
timethis 5000: 1.02551 wallclock secs ( 0.97 usr +  0.06 sys =  1.03 CPU) @
4848.48/s (n=5000)

Windows XP SP3:

Running under Date::Calc::PP version 6.3
timethis 5000: 17.1034 wallclock secs (16.86 usr +  0.00 sys = 16.86 CPU) @
296.58/s (n=5000)
Running under Date::Calc::XS version 6.2
timethis 5000: 1.3329 wallclock secs ( 1.28 usr +  0.00 sys =  1.28 CPU) @
3900.16/s (n=5000)

Another (faster) Windows XP SP3 machine:

Running under Date::Calc::PP version 6.3
timethis 1: 20.5605 wallclock secs (20.55 usr +  0.00 sys = 20.55 CPU) @
486.69/s (n=1)
Running under Date::Calc::XS version 6.2
timethis 1: 1.44224 wallclock secs ( 1.42 usr +  0.00 sys =  1.42 CPU) @
7032.35/s (n=1)

One can see from these results that the XS version quite consistently runs
approximately about 15 times faster than the PP version.

The test script benchmarks a function which calls all functions in
Date::Calc once, each.

Other similar results from XS/PP pairs of modules would be interesting -
maybe not for any practical purposes, but just for the fun of it
(or maybe to give deciders convincing arguments to upgrade to an XS version
or not).

Cheers,
Steffen


benchmark.pl
Description: Binary data


Re: flame bait: execution speed Perl vs. C (Date::Calc::PP vs. Date::Calc::XS)

2009-11-18 Thread O. STeffen BEYer
It might be seen as flame bait because there have been endless discussions
on the Perl vs. C execution speed issue on Perl newsgroups in the past.
:-)

2009/11/18 Kartik Thakore thakore.kar...@gmail.com


 Maybe he thought there were a debate on XS v.s PP performance. If only we
 could be this flame retardent in the uneeded perl5 v.s perl6 debate.

 On 18-Nov-09, at 7:29 AM, Aristotle Pagaltzis pagalt...@gmx.de wrote:

  This is flame bait? Why is this flame bait?




Re: Why you don't want to use /dev/random for testing

2009-11-11 Thread O. STeffen BEYer
Dear Jonathan,

thanks a lot for the link to this very interesting article!

However, a more useful graphical representation of the quality of PRNG’s
would be to take consecutive pairs of random numbers as the (X,Y)
coordinates of a point to plot.

Non-uniform distributions are then easily visible to the naked eye.

It is hard to see any quality differences in the graphs accompanying this
article which are essentially big red rectangles.

It is impossible to see with the naked eye whether the fluctuations in these
graphs are simply due to randomness or to a shortfall of the associated
algorithm.
Does someone here happen to have the necessary plotting software at hand to
provide these pictures, without too much effort?

That would be great!

Thank you!

Best regards,
Steffen


2009/11/11 Jonathan Yu jonathan.i...@gmail.com

 I should note, I wrote an article on this awhile back. Take it with a
 grain of salt, as I'm not an expert in the area; I just wrote bindings
 for the ISAAC algorithm to Perl.

 http://jawnsy.wordpress.com/2009/06/04/performance-of-mathrandomisaac/

 It compares the performance of multiple different PRNG modules (code
 for this is in the Math::Random::ISAAC examples/ directory). I've
 included charts of the distributions generated by them and benchmarks
 of course.



Re: How to best detect availability of C compiler in Makefile.PL?

2009-11-02 Thread O. STeffen BEYer
Hello Aristotle,

I'll answer below:

2009/11/3 Aristotle Pagaltzis pagalt...@gmx.de

 * O. STeffen BEYer ost...@gmail.com [2009-10-13 15:30]:
  I'd rather have the user decide what he/she wants, as in this attached
 file.

 That’s the wrong way to think about it.

 OK, hyperbole; it’s not *wrong*. But it’s very incomplete.

 Don’t forget that there are a lot of people who might merely want
 to use some Perl program, and unlike you and me, they *aren’t*
 Perl programmers. They are merely users of some random Perl code
 that uses your module. Most of these users don’t care which
 version of your module gets installed, and if you ask them to
 pick one anyway, they won’t know how to decide, either. All they
 know is they want the program they care about to work.

 To these people, the option you want to offer is not helpful. It
 is, in fact, a bewildering obstacle.


Yes, I agree.
This is one of the reasons why I have adopted the common approach
of Date::Calc being the pure Perl module, and Date::Calc::XS the
plug-in needing a C compiler.
Another reason was that you would not know which version had
been tested in CPAN::Testers.
And still another reason was that when giving support, it would
be extremely hard to find out which version the user was using.
I would have needed the user to jump through hoops to get this
information.

So for them, you have to provide sensible defaults for all
 options. (And if there isn’t any strong reason to offer an option


That was actually the case (or is - see version 6.1 of Date::Calc!).
The presence of a suitable compiler was determined, and then
Makefile.PL explicitly said what was recommended. By just hitting
Return, the user would get the recommended option.


 in the first place, it shouldn’t even be an option. But that’s
 just a sidenote, since in your case there is solid reason.) That
 means your module should just check for a compiler and install
 with the XS variant by default if possible. The option to change
 that should be provided in such a way that opinionated users can
 get at it without forcing other users to care. (This is probably
 best achieved by checking some environment variable in your *.PL,
 since that passes down easily through the CPAN shell, whereas
 taking a switch would force more manual monkeying.)


 * O. STeffen BEYer ost...@gmail.com [2009-10-13 23:05]:
  Since Date::Calc is such a low-level basic module, it should be
  especially backward compatible, so that even people in old
  production environments (never fix what ain't broken) can
  upgrade my module and benefit from new functions, without
  having to install a load of other modules first - which their
  company policies would probably not permit.

 If they can install Date::Calc, how come they can’t or won’t
 install other modules? OK, maybe they can’t install XS modules.
 I can see that. But if they can install *your* pure-Perl module,
 why can’t they install other pure-Perl modules also?

 This is not the first time I see this argument and I never
 understood it. *headscratch*


Sometimes they can get permission for one module, or at least a well-defined
list of a few modules,
but not for an endless list of modules and dependencies (which the user
frequently does not know exactly
in advance). And permission does not mean that they can install the
module(s) themselves,
no, it means that the administrator is going to install the module(s) for
them. So the less work
this administrator has to do, the more likely to get his/her permission (if
he/she has the power
to decide that, as is sometimes the case in certain companies). And it may
be even more difficult
to get permission from a manager who hasn't a clue what the user is talking
about, and the less
the manager sees a security risk, the better. So the fewer modules, the
better.

Do you understand it now? :-)

Best regards,
Steffen


Re: Date::Calc 6.x and Date::Pcalc 6.x

2009-10-19 Thread O. STeffen BEYer
Hi Jonathan,
and hi to everybody else who might also be concerned:


Hi Steffen:

I was upgrading the package for Date::Calc available in Debian
(libdate-calc-perl) recently and came across the following message in
your CHANGES.txt:
 +  United Date::Calc and Date::Pcalc into a single distribution

Similarly, there is an identical note in the CHANGES.txt for Pcalc as well.

What confuses me about this is that the packages still look to be
separate upstream, and my inference from your changelog entry was that
the packages should be merged (ie, Date::Calc also contains
date::Pcalc), which is not currently the case.

Would you mind elaborating on this further?

Thanks for releasing your work to the CPAN.

Cheers,

Jonathan

Answer:

Date::Calc 6.0: Just Date::Calc as it always used to be (C library plus XS
wrapper plus PM modules), only with some updates (language is not a global
anymore, new normalized mode)
Date::Pcalc 6.0: Just Date::Pcalc as it always used to be (pure-Perl
version), complete rewrite based on Date::Calc 6.0

Date::Calc 6.1: contains Date::Calc 6.0 AND Date::Pcalc 6.0. Depending on
availability of a C compiler and user choice, will install either of the
two, INTO THE Date::Calc NAMESPACE.
Date::Pcalc 6.1: contains Date::Calc 6.0 AND Date::Pcalc 6.0. Depending on
availability of a C compiler and user choice, will install either of the
two, INTO THE Date::Pcalc NAMESPACE.
(This allows to upgrade existing Date::Pcalc installations to a faster C/XS
version without any changes to existing code)

So Date::Calc 6.1 and Date::Pcalc 6.1 are indeed merged - they're just two
slightly differently flavoured embodiments of the same merge

Installing both allows to test e.g. on a machine with C compiler the code
that is being developed for a machine without.
It is also meant to give users more choice as to which upgrade path they
prefer.

Date::Calc 6.2 is essentially the same as Date::Calc 6.1, but without the
C/XS part (it will now always install a pure-Perl version, Date::Calc::PP),
the C/XS part has been outsourced in Date::Calc::XS 6.2
Date::Calc 6.2 is now a wrapper which tries to load Date::Calc::XS 6.2, if
available, and failing that, defaults to Date::Calc::PP.

Does that make it clearer?

Sorry for the confusion!

Best regards,
Steffen


Re: How can I tell MakeMaker to insert recommended modules into META.yml?

2009-10-17 Thread O. STeffen BEYer
In the meantime I found out when this META_MERGE tag works and when not:

When I run a tool from the terminal which calls make dist, everything
works fine.
When I run the same tool from within a cron-job, with stdout and stderr
redirected (to a file and /dev/null, respectively), the extra tags in
META.yml disappear!

Looks like a bug to me...

Best regards,
Steffen

(P.S.: Why do I run the tool from within a cron-job, you may wonder? Because
when doing a make dist, I touch all files and directories first. It
turns out that the size of the dist file varies quite a bit depending on
this time stamp on all files and dirs! So I re-run the make dist every
minute and keep the new dist file if it is smaller. That costs me (or
better, Ralf :-) ) a bit of CPU time, but when several thousand people
download the file, this saves some bandwidth!)

2009/10/16 O. STeffen BEYer ost...@gmail.com

 In the meantime, I found this:
 http://use.perl.org/articles/08/09/06/1541246.shtml

 And with trial and error, I found out this (META_MERGE is the keyword I was
 looking for and couldn't find in any of MakeMakers documentation files):

 WriteMakefile(
 'META_MERGE'= {
'recommends'  =
{
'Carp::Clan' = 6.01,
'Date::Calc::XS' = 6.2
}
},
 'NAME'  = 'Date::Calc',
 'VERSION_FROM'  = 'lib/Date/Calc.pm',
 'ABSTRACT_FROM' = 'lib/Date/Calc.pod',
 'PREREQ_PM' = {
'Carp::Clan'  = 5.3,
'Bit::Vector' = 7.1
},
 'AUTHOR'= 'Steffen Beyer st...@cpan.org',
 'dist'  = { COMPRESS = gzip -9, SUFFIX = gz }
 );

 However, for unknown reasons, this worked once, but later the recommends
 section in META.yml disappeared again. Oops?!?!

 And I still wonder how I can tell MakeMaker to produce more complex
 structures such as this:

 optional_features:
 - opt_csv:
 description:Provides parsing of CSV streams
 requires:
   Text::CSV_XS:0.43
 recommends:
   Text::CSV:   1.12
   Text::CSV_PP:1.20
   Text::CSV_XS:0.65
 - opt_excel:
 description:Provides parsing of Microsoft Excel files
 requires:
   Spreadsheet::ParseExcel: 0.26
   Spreadsheet::ParseExcel::FmtDefault: 0
 recommends:
   Spreadsheet::ParseExcel: 0.49

 Which is supposed to allow the user to make a better informed decision
 whether or not to install certain recommended additional features/modules.

 Any hints on all that?

 Many thanks in advance!!!

 Cheers,
 Steffen


 2009/10/16 O. STeffen BEYer ost...@gmail.com

 How can I tell MakeMaker to insert recommended modules into META.yml?

 When I edit META.yml manually, the next time I run make dist, MakeMaker
 generates META.yml anew and discards my entries.

 What is the right option for WriteMakefile() to tell it that there are
 modules which are not required but recommended?

 Thank you!!!

 Best regards,
 Steffen





Re: How can I tell MakeMaker to insert recommended modules into META.yml?

2009-10-17 Thread O. STeffen BEYer
Hi Jonathan,

in principle, you are completely right!
And yet, in this case you are wrong!

I also do not want my users to have to answer questions; neither do I want
to have to myself.

BUT:

Date::Calc used to be a high-performance module, based on a C library.

Now Date::Calc isn't anymore, it is a wrapper and normally comes with a
pure-Perl implementation plug-in (Date::Calc::PP).

If you want to have the fast module that it used to be, you now have to
install Date::Calc::XS on top, in an additional step.

And I wanted the optional requirement in Date::Calc to notify users that
installing Date::Calc::XS was strongly recommended (if you can, i.e., if you
have a C compiler on your machine).

Moreover, for reasons of backward compatibility with earlier Perl versions
(5.005_03 and older, for instance), Date::Calc
comes with a requirement for Carp::Clan 5.3 (which runs on these older Perl
platforms).

Carp::Clan 6.02 actually also works on Perl 5.005_03, but the tests don't
pass, because they need Test::More, which requires Perl 5.6.

However, whenever you can, it is recommended to install Carp::Clan 6.02,
which has a bugfix that Carp::Clan 5.3 doesn't.

It's not that Carp::Clan 5.3 would not work, it's just that its output is
uglier than it should be.

Again, I would like to notify the users that although only Carp::Clan 5.3 is
required, version 6.02 is actually recommended.

You see?

No answering questions, just informing the users of some important changes!

Cheers,
Steffen


2009/10/17 Jonathan Rockway j...@jrock.us

 * On Fri, Oct 16 2009, O. STeffen BEYer wrote:
  Any hints on all that?

 Wow, a lot of people CC'd on that message.  That is probably Considered
 Annoying to the people you sent it directly to.

 Anyway, optional requirements probably aren't the *worst idea ever
 conceived*, but they are close.  When your module depends on optional
 modules, my module can't just say, requires Foo::Bar, it has to say
 requires Foo::Bar and whatever modules one would need to make your
 optional features work.  This may change from version to version, making
 it impossible to ship a reliable module that depends on yours.

 It is also a problem when communicating with others; when I ask someone
 to try Foo::Bar, I now need to tell them exactly which combination of
 optional modules to install also.  If I can remember.

 Finally, detecting which features to enable at runtime can be flaky.
 Imagine you have a module that enables an optional feature when
 Foo::Quux is installed.  I don't want that feature when I install the
 module, so I skip installing the prereq.  For a while, your module works
 fine.  Some time in the future, I install Foo::Quux to satisfy the
 dependencies for Gorchify::It, and suddenly, your module stops working
 due to auto-detecting Foo::Quux, enabling an optional feature, and then
 not working the same way anymore.  Very bad.  Modules should not work
 differently based on whether or not other random modules happen to be in
 @INC.

 The solution is to make each optional feature a separate distribution;
 then it's easy to depend on the optional feature, easy to remove if you
 don't want it, and easy to communicate to others.

 Also, I can tell you one thing that nobody wants to do while installing
 CPAN modules, and that's answer questions.  I want to say cpan Foo and
 go away and not monitor the terminal it's running in to see if it's
 asking me questions like Do you want to install the module that you
 requested to install? [y].  No... I don't want to install the module I
 just invoked cpan -i on... thanks for asking...

 To summarize: Optional requirements considered harmful.

 Regards,
 Jonathan Rockway

 --
 print just = another = perl = hacker = if $,=$



How can I tell MakeMaker to insert recommended modules into META.yml?

2009-10-16 Thread O. STeffen BEYer
How can I tell MakeMaker to insert recommended modules into META.yml?

When I edit META.yml manually, the next time I run make dist, MakeMaker
generates META.yml anew and discards my entries.

What is the right option for WriteMakefile() to tell it that there are
modules which are not required but recommended?

Thank you!!!

Best regards,
Steffen


Re: How can I tell MakeMaker to insert recommended modules into META.yml?

2009-10-16 Thread O. STeffen BEYer
In the meantime, I found this:
http://use.perl.org/articles/08/09/06/1541246.shtml

And with trial and error, I found out this (META_MERGE is the keyword I was
looking for and couldn't find in any of MakeMakers documentation files):

WriteMakefile(
'META_MERGE'= {
   'recommends'  =
   {
   'Carp::Clan' = 6.01,
   'Date::Calc::XS' = 6.2
   }
   },
'NAME'  = 'Date::Calc',
'VERSION_FROM'  = 'lib/Date/Calc.pm',
'ABSTRACT_FROM' = 'lib/Date/Calc.pod',
'PREREQ_PM' = {
   'Carp::Clan'  = 5.3,
   'Bit::Vector' = 7.1
   },
'AUTHOR'= 'Steffen Beyer st...@cpan.org',
'dist'  = { COMPRESS = gzip -9, SUFFIX = gz }
);

However, for unknown reasons, this worked once, but later the recommends
section in META.yml disappeared again. Oops?!?!

And I still wonder how I can tell MakeMaker to produce more complex
structures such as this:

optional_features:
- opt_csv:
description:Provides parsing of CSV streams
requires:
  Text::CSV_XS:0.43
recommends:
  Text::CSV:   1.12
  Text::CSV_PP:1.20
  Text::CSV_XS:0.65
- opt_excel:
description:Provides parsing of Microsoft Excel files
requires:
  Spreadsheet::ParseExcel: 0.26
  Spreadsheet::ParseExcel::FmtDefault: 0
recommends:
  Spreadsheet::ParseExcel: 0.49

Which is supposed to allow the user to make a better informed decision
whether or not to install certain recommended additional features/modules.

Any hints on all that?

Many thanks in advance!!!

Cheers,
Steffen


2009/10/16 O. STeffen BEYer ost...@gmail.com

 How can I tell MakeMaker to insert recommended modules into META.yml?

 When I edit META.yml manually, the next time I run make dist, MakeMaker
 generates META.yml anew and discards my entries.

 What is the right option for WriteMakefile() to tell it that there are
 modules which are not required but recommended?

 Thank you!!!

 Best regards,
 Steffen



Re: How to best detect availability of C compiler in Makefile.PL?

2009-10-14 Thread O. STeffen BEYer
Hello David,

yes, I had understood that, but I failed to be more explicit about the
problems with legacy platforms:

Often, newer modules are not installed on them, AND/OR newer modules may not
even work on legacy platforms
due to their using Perl features which are newer and not available on older
platforms.

For instance, I am regularly testing all my modules with Perl 5.005_03
before each release.
And they still work on it. Out of the box.

Cheers,
Steffen

P.S.: In the meantime, I have adopted the proposed solution with
ExtUtils::CBuilder.
See also the attached Makefile.PL.


2009/10/14 David Cantrell da...@cantrell.org.uk

 On Tue, Oct 13, 2009 at 11:01:56PM +0200, O. STeffen BEYer wrote:

  Also, many of your suggestions need Perl modules to be installed on the
  target machine which do not exist on legacy Perl installations ...

 Devel::CheckLib is designed to be bundled with your distribution.

 --
 David Cantrell | top google result for internet beard fetish club

  You know you're getting old when you fancy the
  teenager's parent and ignore the teenager
-- Paul M in uknot



Makefile.PL
Description: Binary data


How to best detect availability of C compiler in Makefile.PL?

2009-10-13 Thread O. STeffen BEYer
   Dear Perl module authors,

   what would be the best way to detect whether a working C compiler is
   available at build time of a module (i.e., in Makefile.PL)?

   I would like to install a (faster) XS version of a module if that is the
   case, and a (slower) pure-Perl implementation if not.

   Remember that C compilers are not always available on all systems.
   Sometimes they cost heavy extra money, or sometimes you have to work with
   what's there on a customer's or provider's server (where frequently
   installing a C compiler is not an option due to company policies).

   Thank you!

   Best regards,

   Steffen Beyer

   http://www.engelschall.com/u/sb/download/

   http://search.cpan.org/author/STBEY


Re: How to best detect availability of C compiler in Makefile.PL?

2009-10-13 Thread O. STeffen BEYer
Hi Ryan,

thanks a lot for your fast response (see a copy at the bottom of this
message for convenience)!

But how would I then test both module versions (Date::Calc and Date::Pcalc)
with the same test suite, without duplicating code?

And how would I rely on the Perl version in the C/XS version if something
goes wrong?

Something along these lines?

package Date::Calc;
BEGIN { eval { require bytes; }; }
use strict;
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
@ISA = qw(Exporter DynaLoader);
@EXPORT = qw();
@EXPORT_OK = qw( ... );
%EXPORT_TAGS = (all = [...@export_ok]);
$VERSION = '6.1';

BEGIN # otherwise this comes too late for imports from this module
{
require Exporter;
require DynaLoader;
eval { bootstrap Date::Calc $VERSION; };
if ($@)
{
   local($^W) = 0; # avoid subroutine redefined warnings for the three
subroutines below
   eval { require Date::Pcalc; Date::Pcalc-import(':all'); };
   if ($@) { die Can't find neither the dynamically loadable library
for Date::Calc nor its pure-Perl substitute Date::Pcalc!\n; }
   else { warn Unable to find the dynamically loadable library for
Date::Calc, falling back to its pure-Perl substitute Date::Pcalc!\n; }
}
}

sub Decode_Date_EU2
{
...

Another thing I am wondering about:

You wrote: if something changes later on the module will always continue to
work

I am wondering _what_ could change later (or go wrong), and if it would be
the right thing to do to (silently?) fall back to the pure-Perl version -
maybe even without a warning to the user.

If the Calc.dll (or shared library Calc.so) disappears, this almost
certainly indicates that there is something seriously wrong, which should be
cried about loud and fixed before continuing.

Or if somebody installs a newer Perl version over an existing one, this
could break binary compatibiliy. But I wonder if the eval bootstrap above
would be able to catch that.

Anyway:

In the meantime, I found a way how to detect the compiler in Inline.pm. See
the attached Makefile.PL to see how this would work with Date::Calc.

I am reluctant to install the Perl version no matter what, as you suggested;
I'd rather have the user decide what he/she wants, as in this attached file.

Any opinions on all this, anyone?

Cheers,
Steffen

2009/10/13 Ryan Voots simcop2...@yahoo.com

 On Tuesday 13 October 2009 06:17:47 O. STeffen BEYer wrote:
 Dear Perl module authors,
 
 what would be the best way to detect whether a working C compiler is
 available at build time of a module (i.e., in Makefile.PL)?
 
 I would like to install a (faster) XS version of a module if that is
 the
 case, and a (slower) pure-Perl implementation if not.
 
 Remember that C compilers are not always available on all systems.
 Sometimes they cost heavy extra money, or sometimes you have to work
   with what's there on a customer's or provider's server (where frequently
   installing a C compiler is not an option due to company policies).

 While I've got no idea about detecting the compiler, I would suggest though
 installing the pure perl one no matter what, under a different name and
 having
 the module fall back on it if possible, that way if something changes later
 on
 the module will always continue to work.  This could also simplify the
 build
 and install process since you wouldn't have to decide which one to copy
 during
 make install.




Makefile.PL
Description: Binary data


Re: How to best detect availability of C compiler in Makefile.PL?

2009-10-13 Thread O. STeffen BEYer
Thanks a lot for all your valuable hints!
I had a brief look at all of them.

It seems that most of them are a bit overkill for what I want, or would mean
some ugly messing with the symbol table through exporting imported
identifiers.
I like the straightforward approach that the user can choose at build time
to install either implementation, and can always come back on his decision.
Once the C version is installed, there is no reason to go back to the Perl
version - but it's possible (e.g. for testing of code destined for a
pure-Perl machine).

Also, many of your suggestions need Perl modules to be installed on the
target machine which do not exist on legacy Perl installations.
Since Date::Calc is such a low-level basic module, it should be especially
backward compatible, so that even people in old production environments
(never fix what ain't broken) can upgrade my module and benefit from new
functions, without having to install a load of other modules first - which
their company policies would probably not permit.

ExtUtils::CBuilder though seems a real winner, maybe I'll include this as an
optional way to determine that the C compiler is really present and working,
falling back to the method of scanning %Config and $ENV{PATH} if this module
is not available.

But first of all, I'll give it some more thought!

Thanks again to you all!

Cheers,
Steffen