OMG... Why not use hashmaps? No wonder huge complex scripts compile so incredibly slow. This is going to require some massive overhauling for better performance.

OMG... Why not use hashmaps? No wonder huge complex scripts compile so incredibly slow. This is going to require some massive overhauling for better performance.
https://github.com/remobjects/pascalscript/blob/master/Source/uPSCompiler.pas#L2244

Comments

  1. I'm sure there's a good reason for doing it the way it's done... if you need something faster, look at https://code.google.com/p/dwscript/

    ReplyDelete
  2. Dorin Duminica I am using DWScript in new projects, but I can't just replace PascalScript in my existing product. Aside from breaking backwards compatibility, it'd take way too long to change everything.  DWScript also has some disadvantages that would criple some of the functionality in my application.

    ReplyDelete
  3. The hash seems to be used to reduce as a way to reduce the amount of string comparisons. It's actually quite valid.
    A hashmap could be counter-productive whenever there aren't "many" strings to compare against (depending on your hashmap implementations, that could be "dozens").

    Also you may have a priority issue with a hashmap, the code seems to be getting the last match, which could mean there is also a scoping constraint.

    ReplyDelete
  4. Eric Grange Well, I'm replacing the lists with TDictionary objects that actually use the hash value as key. The performance for small scripts is actually quite alright, at least for the compiler. The compiler really only becomes a problem with huge scripts. As for the priority, it simply allows you to override host-side methods in scripts. In my opinion, that's a design flaw and shouldn't be possible. Given that the engine doesn't support overloading, implementing a simple duplicate identifier exception should resolve the issue.


    On a note, I'm generally not really concerned about compiler performance, but it does present an issue with code completion. Even if it's threaded, the delay generated when compiling huge scripts is significant enough to cause an inconvenience.

    ReplyDelete
  5. I'm not sure it was planned to handle large scripts back in the day of inception. Perhaps Carlo Kok can shed some light?

    ReplyDelete
  6. Well, I can understand the use of the hashes to reduce comparison time, but it goes so far towards improving performance.

    Asbjørn Heid The engine is still used very widespread, so more performance would be nice. It's too bad that RemObjects has moved to basic maintenance of the product. I doubt I'll ever get close to the performance of DWS, but I'd still like to try to squeeze some extra performance out of it. Given that my current application has to satisfy my users until my new DWS based system is completed.

    I've actually tried to implement the "ScriptEngineII" engine, which is actually very similar to PascalScript, but about 10 times faster in execution and adding features like overloading and script-side classes. The downside is that it somehow lacks some very essential features, like supporting (Ansi)Char, Variants, ... I've been working on implementing as much as I can, but it's a slow process.

    ReplyDelete
  7. Overlapping is what is happening here and that's different from overloading, and it has been in Pascal (and most programming languages) since the origin. If you don't support it and error instead, then adding any new functions can break existing scripts.

    ReplyDelete
  8. Eric Grange Well yes, that's what I said. And it could indeed break some scripts. But it will be very limited, as generally, people don't actually use the overlapping, as that completely hides the host-side API function everywhere in the script. Most people who use my application prefix their functions to work around that.

    EDIT: I wasn't aware this was actually a feature in Pascal. There's no reason why the behavior can't be imitated with a hashmap though.

    ReplyDelete
  9. Frédéric Hannes the problem isn't users overlapping functions, but you being forbidden to introduce new functions users may have introduced because they weren't exposed by the host.

    ReplyDelete
  10. Eric Grange I was just thinking about that, but that's already the case now. with hashmaps, that could be easily worked around, since a lookup doesn't take long, it could first be checked if the function is available host-side if it's available in the script.

    Only issue with implementing the TDictionary I've seen so far is that the indexes of the procs list are used for quite a few things.

    ReplyDelete
  11. Asbjørn Heid Frédéric Hannes I wrote this code way before Delphi had any notion of dictionaries and hashmaps, and this was the fastest I could come up with without writing a hashmap myself.

    ReplyDelete
  12. Carlo Kok I figured as much. Do you think there are any critical dependencies of the procedure IDs that can't be removed? If I replace the list for the procedures with a  TDictionary, I could implement a counter to assign IDs to the procedures, rather than using  list indexes. So far, I'm thinking maybe the bytecode format might present issues with removing the dependence on the indexes.

    ReplyDelete
  13. from what I recall "FProcs" is used by index (though really a counter will work just as well). The index for FRegProcs doesn't matter .

    ReplyDelete
  14. Carlo Kok
    Yeah, I've already replaced FRegProcs. I think I can replace most of the usage of FProcs to use TPSProcedure, but for the bytecode format, I'm not entirely sure how to handle it. I'm going to have to take a closer look at the runtime engine first.

    ReplyDelete

Post a Comment