nathankot / company-sourcekit

Completion for Swift projects via SourceKit with the help of SourceKitten
207 stars 16 forks source link

Improve the performance and accuracy #24

Open galeo opened 7 years ago

galeo commented 7 years ago

I don't know if the development of this package is stopped. The last commit date on master branch was 7 months ago (Jun 5, 2016). Is there a change to improve the performance and accuracy?

There is a NeoVim plugin called Autocomplete-swift, which just uses SourceKitten as its back-end. When I tried to code with company-sourcekit(latest) in emacs(25.1.1) like the gif screenshot in its README, it went to totally mass.

screen shot 2017-01-06 at 10 01 44 pm As the above picture shows, when type var|, the completion list appeared, then type SPACE, it got completed like this: screen shot 2017-01-06 at 10 05 54 pm

Going on, type String|, screen shot 2017-01-06 at 10 06 32 pm then type SPACE, got this screen shot 2017-01-06 at 10 06 54 pm

... ...

I use the latest SourceKittenDaemon code compiled with Sourcekitten 0.15.0 and Xcode 8.2 a few days ago.


It seems that SourceKittenDaemon is not actively developed either, will it improve the performance and accuracy by just using SourceKitten as the back-end?

Or could we port Autocomplete-swift into emacs?

Thanks.

nathankot commented 7 years ago

I don't know if the development of this package is stopped. The last commit date on master branch was 7 months ago (Jun 5, 2016). Is there a change to improve the performance and accuracy?

It hasn't stopped, I am still using this package - I've just been satisfied with the results/performance.

It seems that SourceKittenDaemon is not actively developed either, will it improve the performance and accuracy by just using SourceKitten as the back-end?

SourceKittenDaemon does use SourceKitten as the backend, @mitsuse would be great to have your input here on the decision not to use SourcekittenDaemon and how you achieved the performance of your neovim package =D

Or could we port Autocomplete-swift into emacs?

You're more than welcome to :) If it turns out to be better I will probably switch as well. I don't think it's very feasible for company-sourcekit to switch from using SourceKittenDaemon since it will pretty much surmount to a re-write. Also, performance could be a matter of upgrading SourceKitten but looking at their changelog doesn't seem like there are any performance improvements to completion.

galeo commented 7 years ago

The 400k+ issue is still occurred often with endless output writing to sourcekit-output-buffer and the completion results are often not accurate or relevant. It seems that there is still no progress made in completing middle of word (#19).

At first, I think we should compare this package with Autocomplete-swift to find out what we could achieve to improve the results/performance. @mitsuse is appropriate and welcome to do this.

I will try to make an experiment on using SourceKitten as the back-end a few days later. And I'm glad to see continuous improvement aiming at results/performance and more people are joined to make a contribution :)

mitsuse commented 7 years ago

@galeo Hi.

I don't know the implementation of company-sourcekit and whether there are problems on performance, but I can tell about the implementation of autocomplete-swift on the point of completion accuracy. My plugin for Neovim decides the offset of completion as follow:

The second one seems to be related to this issue.

In addition, I think the difference of back-end (SourceKitten or SourceKittenDaemon) is not related to accuracy discussed here as long as I read the source of SourceKittenDaemon few months ago. @nathankot knows this point more than I know because he is a developer of SourceKittenDaemon.

rudedogg commented 7 years ago

I'm really excited to see an issue like this. I'd love to get more info from @nathankot on what can be done to improve performance.

From what I've read it seems like the only way we can get close/improve on Xcode is by caching results from sourcekit? Maybe sourcekittendaemon would be a good place to add that layer? What are your thoughts @nathankot ? I've been casually researching this for a few days.

Some things I found which may (or may not) be useful:

This stuff is a bit over my head - I've never taken a compiler course, etc. But I'd love to help work on this and it looks like other people are interested too!

nathankot commented 7 years ago

@mitsuse

Thanks for your insight, I've added a28ac4811fac929686aca6aa6976845c02d6efd3 which addresses the byte-offset (wasn't using byte length of the prefix.)

@galeo @rudedogg

I did some digging and it seems like the biggest bottleneck for company-sourcekit is actually the http response results being written into the `sourcekit-output` buffer. It takes a good ~2 seconds for 3k lines of output.

Writing response results to a buffer is inevitable in emacs I think, so the question becomes - how do we speed this up? I'm working on a new branch performance trying things like disabling font-lock-mode, so far results don't seem significantly faster. Will look more into it tomorrow, but feel free to take a stab at this.

I would say the second priority here would be to cache word and framework completions, you're right @rudedogg this could be a sourcekittendaemon layer. Depending on how fast we can get the output and JSON parse it, this may or may not be necessary :)

galeo commented 7 years ago

Hi @nathankot,

I have tried to use deferred.el to get the query results asynchronously. It just works well and the *sourcekit-output* buffer becomes useless. As you said above, the performance seems to be improved a little. I will submit a pull request later and you can have a test.

nathankot commented 7 years ago

@galeo not sure how much deferred.el will help since it also outputs to a buffer internally: https://github.com/kiwanami/emacs-deferred/blob/9668749635472a63e7a9282e2124325405199b79/deferred.el#L788

But send in the PR and I can take a look :)

galeo commented 7 years ago

Please have a look at the PR #25 :)

nathankot commented 7 years ago

@galeo I've taken another look and refactored the code, fixed a few things that will hopefully help with performance. Please see the 0.2.0 release notes for full details - and let me know how it goes :)

galeo commented 7 years ago

Hi @nathankot

I pulled the latest code and it works well except when it tries to send the first query request to SourceKittenDaemon, it outputs the following messages:

Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8081/project.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8082/project.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8083/project.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8084/project.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8085/project.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8086/project.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8087/project.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8088/project.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8089/project.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8090/project.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8081/ping.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8081/project.
Blocking call to accept-process-output with quit inhibited!!
REQUEST [error] Error (error) while connecting to http://localhost:8082/project.
Blocking call to accept-process-output with quit inhibited!! [2 times]
REQUEST [error] Error (error) while connecting to http://localhost:8083/project.
Blocking call to accept-process-output with quit inhibited!!
REQUEST [error] Error (error) while connecting to http://localhost:8084/project.
Blocking call to accept-process-output with quit inhibited!!
REQUEST [error] Error (error) while connecting to http://localhost:8085/project.
Blocking call to accept-process-output with quit inhibited!!
REQUEST [error] Error (error) while connecting to http://localhost:8086/project.
Blocking call to accept-process-output with quit inhibited!!
REQUEST [error] Error (error) while connecting to http://localhost:8087/project.
Blocking call to accept-process-output with quit inhibited!!
REQUEST [error] Error (error) while connecting to http://localhost:8088/project.
Blocking call to accept-process-output with quit inhibited!!
REQUEST [error] Error (error) while connecting to http://localhost:8089/project.
Blocking call to accept-process-output with quit inhibited!!
REQUEST [error] Error (error) while connecting to http://localhost:8090/project.

And I personally think the message [sourcekit] got query response should better be silenced when sourcekit-verbose is nil.

Another problem I noticed recently: when typed fast, it may establish lots of query requests and it suffers a serious delay to get the response results. screen shot 2017-01-26 at 9 52 57 pm

I experimented to improve the accuracy by tweaking the prefix and making company-sourcekit work with other backends, eg. company-keywords, company-yasnippet etc. I don't have enough time on this and there is only a little progress. The query results should better be filtered and cached with a flexible and robust mechanism. I see you've added a string match filter to the query result and it could be a good beginning. Thanks :)

Pitometsu commented 7 years ago

@galeo did you achieve any progress with this?

jojojames commented 6 years ago

Depending on how fast we can get the output and JSON parse it, this may or may not be necessary :)

Emacs master now has JSON encoding in C by the way. Not sure how much it'll help this problem.