Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vector example #131

Merged
merged 1 commit into from
Jun 6, 2017
Merged

Vector example #131

merged 1 commit into from
Jun 6, 2017

Conversation

mhyee
Copy link
Member

@mhyee mhyee commented May 23, 2017

It started as a vector example, but grew to encompass an object model and also a linked list.

Objects are implemented as a 2-array. The first cell is the type ID and the second cell is a reference to the object map, which contains all the fields and methods. Additional fields and methods can be added to an existing object.

For simplicity, the object map is implemented as a linked list. A growable array would have been more difficult to implement, and in fact, is already implemented as the example object. (I didn't want to implement it twice.)

The vector object consists of an array that doubles in size whenever it needs to be grown. It supports getting/setting, and later, a map function is added to the object.

The example is thoroughly documented and tested. The optimized version runs fine and passes the tests. However, the optimized version fails due to bugs in the optimization passes, see #133.

@mhyee mhyee changed the title [WIP] Vector example Vector example May 31, 2017
@mhyee
Copy link
Member Author

mhyee commented May 31, 2017

The example is now done, though there are still bugs in the optimizer.

Please let me know what you think; maybe some functions need to be simplified.

@o-
Copy link
Contributor

o- commented May 31, 2017

I am currently looking at the optimizer bugs

@o-
Copy link
Contributor

o- commented May 31, 2017

@mhyee rebased on top of #138 this now compiles. But the optimized version runs into an assertion error. Not yet sure why.

@o-
Copy link
Contributor

o- commented May 31, 2017

@mhyee on top of the newest changes to #138 it now passes the tests :)

@aviralg
Copy link
Contributor

aviralg commented Jun 5, 2017

@mhyee I would love to know what happens if you run this with inlining.

@mhyee
Copy link
Member Author

mhyee commented Jun 6, 2017

Rebased. Thanks to @o- for fixing the optimizer bugs. However, it looks like the example still needs #136.

Inlining a large program like the vector is very, very slow. Running test_examples_long made me think I hit an infinite loop. I'm guessing that trying to prune the inlined program is the problem.

Also, it's faster to optimize+run the program than it is to optimize, redirect the output to a separate file, and then run that file without an optimization pass. I'm guessing that reading in the file and parsing it takes a lot of time.

Baseline

$ wc -l examples/vector.sou
     689 examples/vector.sou

$ time ./sourir examples/vector.sou > /dev/null

real	0m0.100s
user	0m0.081s
sys	0m0.004s

Inlining

$ time ./sourir examples/vector.sou --opt inline > inlined.sou

real	0m15.597s
user	0m15.394s
sys	0m0.081s

After fixing up inlined.sou (removing extra output):

$ wc -l inlined.sou
  171058 inlined.sou

$ time ./sourir inlined.sou > /dev/null

real	0m34.708s
user	0m34.218s
sys	0m0.215s

Inlining+constant folding

$ time ./sourir examples/vector.sou --opt inline,const_fold > inlined-cf.sou

real	0m23.425s
user	0m23.019s
sys	0m0.157s

After fixing up inlined-cf.sou (removing extra output):

$ wc -l inlined-cf.sou
  171026 inlined-cf.sou

Then there's some bug, because there's a line:

x <- nil[i]

Running the code directly after optimization is fine, because this line is in unreachable code. But redirecting it to output means it needs to be re-parsed, and this is a parsing error.

@aviralg
Copy link
Contributor

aviralg commented Jun 6, 2017

I just now tried this example. Here are the numbers on my machine for comparison.

Inline original program

$ time ./sourir examples/vector.sou --opt inline > inlined.sou
8.58s  user 
0.02s  system 
8.597  total

Constant-fold inlined program

$ time ./sourir inlined.sou --opt const_fold > inlined_cf_1.sou
22.46s  user 
0.00s   system 
22.467  total

Inline then constant-fold original program

$ time ./sourir examples/vector.sou --opt inline,const_fold > inlined_cf_2.sou
12.05s  user 
0.03s   system 
12.083  total

After inlining, the increase in code size is about - 171026/689 = 248.22

The number of inlinings performed = 83

I used Unix.gettimeofday to measure the time taken by key operations in the inlining code. Here are the results -

compute_inlining_order :  0.000137
replace_vars           :  0.054215
replace_labels         :  0.054614
replace_returns        :  0.180461
insert_prologue        :  0.000197
insert_epilogue        :  0.000093
total_time             :  0.352313

I wonder if most time is spent parsing and disassembling code.

@mhyee
Copy link
Member Author

mhyee commented Jun 6, 2017

Native compiler makes the vector example 3x faster, but it's still slow.

$ time ./sourir examples/vector.sou > /dev/null

real	0m0.042s
user	0m0.015s
sys	0m0.004s

$ time ./sourir examples/vector.sou --opt inline > /dev/null

real	0m5.047s
user	0m4.982s
sys	0m0.048s

$ time ./sourir inlined.sou > /dev/null

real	0m11.235s
user	0m11.067s
sys	0m0.065s

$ time ./sourir examples/vector.sou --opt inline,const_fold > /dev/null

real	0m7.128s
user	0m7.027s
sys	0m0.043s

@gasche
Copy link
Collaborator

gasche commented Jun 6, 2017

Looking at the result of inlining vector.sou reveals plenty of opportunities for making the optimizations a bit more aggressive, in particular constant folding. Consider for example (this is the output of --opt inline,cont_fold):

 array a2[0]
 [...]
 var args_11_1 = a2
  [...]
 branch (args_11_1 == nil) $error_1_22_1 $checklen_1

This branch should be eliminated. Later:

 arrlen_1 <- length(args_11_1)
 branch (arrlen_1 < 0) $error_2_22_1 $loop_1a_1

This test can also be eliminated.

This is precisely the sort of things that Jan mentioned early during the project: the code that gets produced by speculation/traces for a dynamic language tends to be very ugly, and simple optimizations can do a lot. I think it would be nice to do something here.

@gasche
Copy link
Collaborator

gasche commented Jun 6, 2017

Our first priority with regard to this PR is to find a way to merge it without making our testsuite explode. Ming-ho, could you just move this file to some other place than examples/, so that we have it in the repo for testing?

@gasche
Copy link
Collaborator

gasche commented Jun 6, 2017

The same file also has (after inlining and constant-folding):

branch true $error_1_21_1 $checklen

which suggests the cleanup passes should also be strengthened. (Note that what we can do here is strengthened by the enforced label invariants, we know that $checklen is dead code and that $error_1_21_1 can be just moved there.)

@mhyee
Copy link
Member Author

mhyee commented Jun 6, 2017

I renamed the file so it's not picked up by the test runner.

Note that the test runner does not apply the inline phase. I'll send a PR for that (after confirming that the Travis build time is still reasonable).

I'll open a new issue to track these new optimization opportunities.

@mhyee mhyee merged commit 21dfbc4 into reactorlabs:master Jun 6, 2017
@mhyee mhyee deleted the vector-example branch June 6, 2017 18:14
This was referenced Jun 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants