antlr / antlr4

ANTLR (ANother Tool for Language Recognition) is a powerful parser generator for reading, processing, executing, or translating structured text or binary files.
http://antlr.org
BSD 3-Clause "New" or "Revised" License
16.93k stars 3.26k forks source link

[Swift] Swift Runtime Performance Problem #2434

Open AwayQu opened 5 years ago

AwayQu commented 5 years ago

I both use antlr4 in java and swift to parse the same source code, but I find that swift runtime slow than java runtime.

For this code DDTTYLogger.m , java cost 3s, swift cost 22s.

Sample Code is simple.

       ANTLRInputStream inputStream = new ANTLRFileStream("/path/to/DDTTYLogger.m");

        ObjectiveCLexer lexer = new ObjectiveCLexer(inputStream);

        CommonTokenStream tokens = new CommonTokenStream(lexer);

        ObjectiveCParser parser = new ObjectiveCParser(tokens);

        ParseTree tree = parser.translationUnit();

        long endTime=System.currentTimeMillis();

        System.out.println("cost:"+(endTime-startTime)+"ms");
        let startTime = CFAbsoluteTimeGetCurrent()
        let ins = try! ANTLRFileStream("/path/to/DDTTYLogger.m")
        let lexer = ObjectiveCLexer(ins)
        let tokens = CommonTokenStream(lexer)
        let parser = try! ObjectiveCParser(tokens)
        do {
            let tree = try  parser.translationUnit()
            let endTime = CFAbsoluteTimeGetCurrent()
            debugPrint("「translationUnit」time : \(Date()) cost:\(endTime - startTime) s")
        } catch let err {
            print("parse err: \(err)")
        }
ewanmellor commented 5 years ago

@AwayQu Which versions of Antlr and Swift are you using? And which operating system?

AwayQu commented 5 years ago

@ewanmellor Version of Antlr: I use the forked antlr repo's master, and merged your branch of fix Swift 4.2 error ewanmellor-fix-swift-4.2

Swift Version: 4.2

Operating Version: Mac OS Mojave

ewanmellor commented 5 years ago

@AwayQu Which grammar are you using?

ewanmellor commented 5 years ago

@AwayQu Please also confirm that you are using a release build, not a debug build. I'm seeing differences of 4 secs vs 18 seconds between release and debug builds, so it makes a very big difference.

[Edited: I previously said 57 seconds for debug builds here, but I think that was a bad measurement and I'm withdrawing it.]

ewanmellor commented 5 years ago

@AwayQu Please try https://github.com/ewanmellor/antlr4/tree/swift-micro-optimizations . I would be interested to know if those changes make any difference for you.

AwayQu commented 5 years ago

@ewanmellor I use objc & java8 grammer, I always use debug version build, I will try to use release build and the https://github.com/ewanmellor/antlr4/tree/swift-micro-optimizations branch tonight. And give you some feedback.

AwayQu commented 5 years ago

@ewanmellor I remember I had tried time profile when I found swift version parse need 20s. The time profile (which use release config)shows parse only cost 5s , I confused at that time then open this issue. I think you mentioned use release configuration should be helpful for me.

ewanmellor commented 5 years ago

@AwayQu Do you mean this grammar? https://github.com/antlr/grammars-v4/tree/master/objc

I tried that one and got an error because "postfix" is a keyword in Swift. After renaming that, it parses your DDTTYLogger.m with errors, but it does complete:

line 719:51 token recognition error at: '/N'
line 719:59 token recognition error at: '.h'
line 1201:21 no viable alternative at input 'msgStack['
line 1201:49 extraneous input ']' expecting {'auto', 'break', 'char', 'const', 'continue', 'do', 'double', 'enum', 'extern', 'float', 'for', 'goto', IF, 'inline', 'int', 'long', 'register', 'restrict', 'return', 'short', 'signed', 'sizeof', 'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while', 'true', 'false', 'BOOL', 'Class', 'bycopy', 'byref', 'id', 'IMP', 'in', 'inout', 'nil', 'NO', 'NULL', 'oneway', 'out', 'Protocol', 'SEL', 'self', 'super', 'YES', '@autoreleasepool', '@encode', '@protocol', '@selector', '@synchronized', '@throw', '@try', 'atomic', 'nonatomic', 'retain', '__attribute__', '__autoreleasing', '__block', '__bridge', '__bridge_retained', '__bridge_transfer', '__covariant', '__contravariant', '__deprecated', '__kindof', '__strong', TYPEOF, '__unsafe_unretained', '__unused', '__weak', NULL_UNSPECIFIED, NULLABLE, NONNULL, 'null_resettable', 'NS_INLINE', 'NS_ENUM', 'NS_OPTIONS', 'assign', 'copy', 'getter', 'setter', 'strong', 'readonly', 'readwrite', 'weak', 'unsafe_unretained', 'IBOutlet', 'IBOutletCollection', 'IBInspectable', 'IB_DESIGNABLE', IDENTIFIER, LP, '{', '}', '[', ';', '@', BANG, '~', '++', '--', '+', '-', '*', '&', '^', CHARACTER_LITERAL, STRING_START, HEX_LITERAL, OCTAL_LITERAL, BINARY_LITERAL, DECIMAL_LITERAL, FLOATING_POINT_LITERAL}
"「translationUnit」time : 2018-12-05 05:25:43 +0000 cost:4.5481380224227905 s"

In my tests, Release build is 4.5 secs, Debug build is 17.5 secs.

AwayQu commented 5 years ago

@ewanmellor Yes, this grammer https://github.com/antlr/grammars-v4/tree/master/objc.

AwayQu commented 5 years ago

@ewanmellor https://github.com/ewanmellor/antlr4/tree/swift-micro-optimizations

I had tried this branch. Less 1/6 - 1/5 time cost than before. It's nice.

jam0128 commented 4 years ago

@ewanmellor hello! I have same swift4.2 runtime slow issue on current master branch. So I am currently going to test with this branch for test - https://github.com/ewanmellor/antlr4/tree/swift-micro-optimizations Is it okay to use this optimizations branch?(It seems like 'This branch is 9 commits ahead, 313 commits behind antlr:master.') Thanks to listen :)

ewanmellor commented 4 years ago

@jam0128 You are welcome to cherry-pick those changes and see if any of them make things better for you. That branch is so far behind because master has moved to Swift 5, so you might have some conflicts to fix.

None of the changes were particularly effective in my testing, which is why they didn't go into master. If you see improvements from any of them, please let me know.

I'm not active on Antlr at the moment, and I won't be for a while, so I can't help any further. I'm happy to submit patches though if you find that they are a big improvement.

By far the biggest performance improvement comes from compiling in Release mode, so definitely make sure that you are doing that before wasting too much time. Other than that, I don't think anyone has a good idea why performance dropped off so badly around Swift 4.2 / Swift 5.