mighty-gerbils / gerbil

Gerbil Scheme
https://cons.io
GNU Lesser General Public License v2.1
1.15k stars 111 forks source link

Interface Specializers #1127

Closed vyzo closed 7 months ago

vyzo commented 7 months ago

On top of ##1126

And so it begins... the compiler generates specializers for all bound methods that could benefit from it, and interface prototype creation plugs to it, with wondrous performance results for certain programs.

Here is an example:

(defclass A (x y))
(defclass (B A) (z))

(defmethod {linear A}
  (lambda (self w)
    (fx+ (fx* (A-x self) w) (A-y self))))

(defmethod {bilinear-combination B}
  (lambda (self w z)
    {self.bilinear {self.linear w} z}))

(defmethod {bilinear B}
  (lambda (self lc z)
    (fx+ lc (fx* (B-z self) z))))

(interface Combinator
  (bilinear-combination w z))

(def (run iters)
  (let (instance (Combinator (B x: 1 y: 2 z: 3)))
    (for (i (in-range iters))
      (let (result (&Combinator-bilinear-combination instance 4 5))
        (unless (= result 21)
          (error "bad result" result: result expected: 21))))))

(def (main iters)
  (let (iters (string->number iters))
    (time (run iters))))

With gxc master:

$ gxc -exe -o /tmp/ispec-bench -O src/gerbil/test/interface-specialization-bench.ss
/tmp/gxc.1708454081.817515/test__interface-specialization-bench.scm:
/tmp/ispec-bench__exe.scm:
/tmp/gxc.1708454081.817515/test__interface-specialization-bench.c:
/tmp/ispec-bench__exe.c:
/tmp/ispec-bench__exe_.c:
$ /tmp/ispec-bench 1000000
(time (let () (declare (not safe)) (test/interface-specialization-bench#run _iters79_)))
    0.215345 secs real time
    0.215332 secs cpu time (0.211338 user, 0.003994 system)
    20 collections accounting for 0.016191 secs real time (0.015828 user, 0.000356 system)
    159892208 bytes allocated
    671 minor faults
    no major faults
    562301090 cpu cycles

With the specializers:

$ ./build.sh env gxc -exe -o /tmp/ispec-bench -O gerbil/test/interface-specialization-bench.ss
/tmp/gxc.1708454105.0922964/test__interface-specialization-bench.scm:
/tmp/ispec-bench__exe.scm:
/tmp/gxc.1708454105.0922964/test__interface-specialization-bench.c:
/tmp/ispec-bench__exe.c:
/tmp/ispec-bench__exe_.c:
[*] Done
$ /tmp/ispec-bench 1000000
(time (let () (declare (not safe)) (test/interface-specialization-bench#run _iters79_)))
    0.010587 secs real time
    0.010587 secs cpu time (0.010586 user, 0.000001 system)
    no collections
    1408 bytes allocated
    no minor faults
    no major faults
    27638154 cpu cycles

20x, not bad huh?

Basically all the dynamic dispatch call cost of the MOP for self references (slots or methods) has disappeared.

fare commented 7 months ago

I'd like to see more documentation comments and type signature comments above all functions everywhere.

vyzo commented 7 months ago

rebased on master.

netlify[bot] commented 7 months ago

Deploy Preview for elastic-ritchie-8f47f9 ready!

Name Link
Latest commit 8a7f9bc47afe50333d587d808c72439562fb08e4
Latest deploy log https://app.netlify.com/sites/elastic-ritchie-8f47f9/deploys/65d50dbe842c170008ae8de9
Deploy Preview https://deploy-preview-1127--elastic-ritchie-8f47f9.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

vyzo commented 7 months ago

Added some more comments; we need to write docs, the code is mostly self explanatory with a good mop page in the hyperspec.