xp-framework/rfc — Issue #83: Define classes through stream wrappers
Author: kiesel
Created: 2011-10-17 15:52:30+00:00
State: closed
Labels: framework, implemented

Scope of Change
====
The ClassLoader's defineClass() method will be changed to use
include() with an own stream wrapper instead of eval().

Rationale
====
In case the class brings up a fatal error at runtime, a
meaningful error message can be shown instead of a message
like "Fatal error at eval'ed code at line XXX in
lang/ClassLoader.class.php".

Functionality
====
The defineClass() method will prepare a string containing the
bytes of the new class and store pass it to a class implementing
the stream_* functions.

Instead of calling eval() with that string, it will include() the
new class with the artificial "inline://"-protocol - invoking the
stream wrapper.
The stream_wrapper returns the class bytes. PHP will be able to
associate a constructed filename with the inline code and show
that in any case of error.

Security considerations
====
n/a

Speed impact
====
The new execution model is around 3-4 times slower than the
previous!
This insight has been made through the following simple benchmark
script:

Benchmark script:

```php
defineClass(
'net.xp_framework.runtime.DefinedClass'.$i,
'class DefinedClass'.$i.' extends Object {}'
);
}

?>
```

Old execution speed:
ak@boost ~/devel/xp.public/trunk $ time php test.php

real 0m7.850s
user 0m7.300s
sys 0m0.550s

New execution speed:
ak@boost ~/devel/xp.public/trunk $ time php test.php

real 0m25.181s
user 0m22.090s
sys 0m3.080s

The slow execution is probably due to many additional PHP userland function
calls and string manipulations. However, defining a class is usually not
a task that happens nearly that often as in the provided benchmark script.

The developer community has to decide whether the useful additional debugging
information outweights the speed loss.

Dependencies
====
n/a

Related documents
====
- http://xp-framework.net/rfc/contrib/rfc0083.diff