Author Topic: lexer file loading ...  (Read 17031 times)

Offline tiwag

  • Developer
  • Lives here!
  • *****
  • Posts: 1196
  • sailing away ...
    • tiwag.cb
lexer file loading ...
« on: April 04, 2006, 03:12:29 pm »
... lasts ages  :(

i think this point should really be improved.

what can be done to improve the loading time of these lexer files ?  :)

Offline Michael

  • Lives here!
  • ****
  • Posts: 1608
Re: lexer file loading ...
« Reply #1 on: April 04, 2006, 03:25:00 pm »
Hello,

May be it could be useful to just load only the "most important" of them at the beginning (C::B default) and then let the user decides if she/he needs additional ones or not (as with the plugins). For example, I do not use f77 lexer, so why I have to load it?

Additionally, a background thread could be used to load the lexers. Moreover, the use of SAX could also be helpful to speed up the process.

Best wishes,
Michael

Offline mandrav

  • Project Leader
  • Administrator
  • Lives here!
  • *****
  • Posts: 4315
    • Code::Blocks IDE
Re: lexer file loading ...
« Reply #2 on: April 04, 2006, 03:51:51 pm »
This is the speed penalty we have to pay for using TinyXML. It makes everything easier for us, but it's a little slow, especially when parsing large nodes (like the lexers' keywords)...
Be patient!
This bug will be fixed soon...

Offline Michael

  • Lives here!
  • ****
  • Posts: 1608
Re: lexer file loading ...
« Reply #3 on: April 04, 2006, 04:06:52 pm »
This is the speed penalty we have to pay for using TinyXML. It makes everything easier for us, but it's a little slow, especially when parsing large nodes (like the lexers' keywords)...

Yes, TinyXML is a nice piece of code. Pity that it does not implement SAX or pull SAX.

Best wishes,
Michael

Offline Ceniza

  • Developer
  • Lives here!
  • *****
  • Posts: 1441
    • CenizaSOFT
Re: lexer file loading ...
« Reply #4 on: April 04, 2006, 04:34:35 pm »
Wow, thinking about how slow was Code::Blocks loading because of those lexers was the last thing I did when I went to sleep. Now I wake up and I find a post about it.

Are you spying me? :P

I support Michael's idea of just loading the most important ones and somehow letting the user decide if more lexers should be loaded later.

That would also add an extra Tip Of The Day :)

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: lexer file loading ...
« Reply #5 on: April 04, 2006, 06:01:29 pm »
Michael's approach is good, as it addresses the actual problem, which is not TinyXML being slow, but loading many lexers that are unneeded.
Face it, we have more lexers that are complete nonsense than lexers that are actually used by anyone. Out of the 22 lexers loaded at startup, the "average" user will use 2, maybe 3.

Peeking into the sources for 10 seconds, I found an additional issue with lexer loading that has not been noticed so far: it is not Unicode-safe. I wonder nobody has complained about lexers not working at all in Czech and Russian installations yet...  :shock:

Being fed up with my other stuff at the moment, I'll have a look at what can be done about lexer loading after dinner :)
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

takeshimiya

  • Guest
Re: lexer file loading ...
« Reply #6 on: April 04, 2006, 11:59:21 pm »
I've spent various days trying to understand this issue (why the C::B loading was slow).

Limiting the loaded lexers could be a temporal quick fix until a better solution is implemented.

Here are some of my tests on my pc:
C::B loading on first time: 15 seconds. C::B loading on subsequent times: 5 seconds.
The lexers parsing take a constant time everytime, and the difference between the first and subsequent time is mostly attributed to the DLLs loading.
TinyXML parsing is slow, with a rough measure of 200ms each lexer.


A bottom note:
At my univ. which I can only load C::B from the LAN, C::B takes 50 seconds to load. SciTE takes 1 second.
SciTE loads way more lexers than C::B. The SciTE lexers also have more features.
We can do better. :)

There are multiple ways to improve things. It needs time.

Offline Michael

  • Lives here!
  • ****
  • Posts: 1608
Re: lexer file loading ...
« Reply #7 on: April 05, 2006, 09:51:14 am »
May be it could be useful to just load only the "most important" of them at the beginning (C::B default) and then let the user decides if she/he needs additional ones or not (as with the plugins). For example, I do not use f77 lexer, so why I have to load it?

Hello,

I have had some time to thinking about an alternative :). May be lexers could be handle as file associations are. Depending on which kind of file a user open, C::B loads the relative lexer automatically. So, it would not be necessary to load at the beginning 2-3 basic lexers (to decide which of them could not be so easier...).

By default C::B has pre-defined associations (stored into the C::B config file?). Each type of file has its lexer. The user has the possibility to modify this list by either adding a new lexer and its relative file type association and/or to modify an existing one. User specific lexers could be stored separately into the C::B config file (or an alternative lexer config file).

May be the lexers used by project or workspace could be stored into .cbp or .workspace files, so that when loading a project or workspace, C::B loads directly the necessary lexers without having to parser the file types to get the corresponding lexers.

This method has the advantage to make the handling of lexers automatic with "no" or very limited additional overhaed for the user. The disadvantage is a bit more overhead for C::B as it would be necessary to e.g., check that a lexer is not loaded several times.

If you have questions and or comments, please do not hesitate :).

Best wishes,
Michael

Offline mandrav

  • Project Leader
  • Administrator
  • Lives here!
  • *****
  • Posts: 4315
    • Code::Blocks IDE
Re: lexer file loading ...
« Reply #8 on: April 05, 2006, 11:28:14 am »
Revision 2306 has fixed the delay when opening "Settings->Editor". That's a start ;).
Be patient!
This bug will be fixed soon...

Offline Michael

  • Lives here!
  • ****
  • Posts: 1608
Re: lexer file loading ...
« Reply #9 on: April 05, 2006, 11:38:44 am »
Revision 2306 has fixed the delay when opening "Settings->Editor". That's a start ;).

Great :D.

I have remarked that this morning there were several commits. Each time I have built a C::B revision, I have discovered a new one :D.

Best wishes,
Michael

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: lexer file loading ...
« Reply #10 on: April 05, 2006, 11:50:19 am »
May be lexers could be handle as file associations are. Depending on which kind of file a user open, C::B loads the relative lexer automatically [...]
I have been trying to implement just that last evening, but it is not as easy as you think. First, you don't know what a lexer refers to without loading it. Thus, you would have to encode this information somewhere. Keeping around an extra map file for this would work best, but then you are building up a dependency which is not good. When adding a new lexer, you have to update the map, or it won't work.
One could think about putting the extension which is handled into the lexer's name, but most lexers handle several (up to 6) file types, so filenames would become quite cluttered (still possible).

Quote
By default C::B has pre-defined associations (stored into the C::B config file?).
Hardcoded at the present time. We discussed this in January when restructuring the file association code, but decided to leave it hardcoded for now to not further complicate things.

Quote
Each type of file has its lexer. The user has the possibility to modify this list by either adding a new lexer and its relative file type association and/or to modify an existing one. User specific lexers could be stored separately into the C::B config file (or an alternative lexer config file).
That's basically how it used to be in the dark ages when all lexers were copied to the configuration. Currently, only differences are stored to the config.

My current plan is to scan the lexer folder once and load all lexers once. That provides us with a mapping of extensions to lexers which can be saved in the config file. On subsequent loads, Code::Blocks will know which lexer to load when opening a specific file type, and that can indeed be done on request then. When installing a new lexer, one would have to hit the "refresh button" to force reloading the map. That way, you don't need to configure anything, which is a good thing. I am still looking for a weak spot in this approach, but I guess it might just work fine.
What do you think about this approach?


Quote
TinyXML parsing is slow, with a rough measure of 200ms each lexer. [...]
SciTE loads way more lexers than C::B. The SciTE lexers also have more features.
You're comparing apples and oranges again. SciTE lexers have a collection of single line key/value pairs, and Code::Blocks lexers are xml documents that are validated for well-formedness. Of course it takes time to validate a document, this is not surprising.
The same goes for your network load story. You're missing the point here, too.
We are making on the order of 13,000 isolated file accesses during a "normal" startup. On a local file system, much of this can be cached, but it is absolutely not surprising that this is a major performance bottleneck over a network.
wxWidgets makes on the order of 10,000 distinct file accesses alone to load the XRC files. You can easily verify this using FileMon if you have any doubts about it.
To get back to TinyXML which is so terribly slow: the configuration file loads with about 6-7 file accesses, and all lexers are loaded using about 100 distinct file accesses. The time that TinyXML takes to parse those files is just ridiculous compared to the network latency of 10k accesses...
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline Michael

  • Lives here!
  • ****
  • Posts: 1608
Re: lexer file loading ...
« Reply #11 on: April 05, 2006, 02:49:21 pm »
May be lexers could be handle as file associations are. Depending on which kind of file a user open, C::B loads the relative lexer automatically [...]
First, you don't know what a lexer refers to without loading it.

In my idea, you have a table where for each lexer there are the file extensions supported. But instead of putting just the lexer name, you put its path (possibly relative) and its name (as alternative, just the lexer filename and the lexer folder path stored separately). In a similar way as for the include files and libraries. In this case C::B knows which lexer it has to load (without before parsing all the lexers).

Thus, you would have to encode this information somewhere. Keeping around an extra map file for this would work best, but then you are building up a dependency which is not good. When adding a new lexer, you have to update the map, or it won't work.
One could think about putting the extension which is handled into the lexer's name, but most lexers handle several (up to 6) file types, so filenames would become quite cluttered (still possible).

The information could be stored into an XML file. When C::B starts, it loads the XML file, parses it, gets the info and fills the table. When a user add/modify a lexer/extension, this can be easily saved into the XML file. May be a multimap can be used, where the lexer "name" would be the key and the extensions the values.

Disadvantage is that you build some dependencies which is not good.

My current plan is to scan the lexer folder once and load all lexers once. That provides us with a mapping of extensions to lexers which can be saved in the config file. On subsequent loads, Code::Blocks will know which lexer to load when opening a specific file type, and that can indeed be done on request then. When installing a new lexer, one would have to hit the "refresh button" to force reloading the map. That way, you don't need to configure anything, which is a good thing. I am still looking for a weak spot in this approach, but I guess it might just work fine.
What do you think about this approach?

I think it is a good alternative :). The question is how to manage the updates of the map (addition, deletion, modification of a lexer). E.g., if you add/modify a lexer would C::B re-parses all the lexer again or just to new/modified one? If you re-scan all the lexers (easiest solution), it would take time and may be the user will not appreciate. May be a thread with low priority could be used to manage this update process.

Anyway, as you say it should work fine :). May be to spot some problems, at the beginning a simple implementation could be used. If no major problems are reported, it could be extended and improved. It would be not so good if a large amount of time is invested at the beginning, just to know that the idea will not work. Better beginning with a simple solution and extend it successively.

Best wishes,
Michael

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: lexer file loading ...
« Reply #12 on: April 05, 2006, 03:08:19 pm »
Quote
I think it is a good alternative Smile. The question is how to manage the updates of the map (addition, deletion, modification of a lexer). E.g., if you add/modify a lexer would C::B re-parses all the lexer again or just to new/modified one? If you re-scan all the lexers (easiest solution), it would take time and may be the user will not appreciate. May be a thread with low priority could be used to manage this update process.
Modifying a lexer should not matter at all (unless you change the file mapping). Reparsing everything from scratch is very attractive, as it is simple to implement. It may take 3-5 seconds, but so what... you don't add new lexers every day :)
Deletion should not be a problem, if the file is not found, you simply return the same value (called LEX_NONE or something) that is returned if a lexer is not known at all.

Putting those extension/file mappings into the config is probably the least painful. I would not want to require the user to edit a configuration file by hand just to add a lexer. Also, this would not work well with internet update/install. To modify an external file, we would need to either implement a complete parser or distribute a tool like sed or something with Code::Blocks. On the other hand, allowing the updater to fire a "reload lexers" event is trivial and 100% safe.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline Michael

  • Lives here!
  • ****
  • Posts: 1608
Re: lexer file loading ...
« Reply #13 on: April 05, 2006, 03:45:06 pm »
Quote
I think it is a good alternative Smile. The question is how to manage the updates of the map (addition, deletion, modification of a lexer). E.g., if you add/modify a lexer would C::B re-parses all the lexer again or just to new/modified one? If you re-scan all the lexers (easiest solution), it would take time and may be the user will not appreciate. May be a thread with low priority could be used to manage this update process.
Modifying a lexer should not matter at all (unless you change the file mapping). Reparsing everything from scratch is very attractive, as it is simple to implement. It may take 3-5 seconds, but so what... you don't add new lexers every day :)
Deletion should not be a problem, if the file is not found, you simply return the same value (called LEX_NONE or something) that is returned if a lexer is not known at all.

If it takes around 5 second or so, I think it is not an issue. And yes, you do not add a lexer each day :).

Putting those extension/file mappings into the config is probably the least painful. I would not want to require the user to edit a configuration file by hand just to add a lexer. Also, this would not work well with internet update/install. To modify an external file, we would need to either implement a complete parser or distribute a tool like sed or something with Code::Blocks. On the other hand, allowing the updater to fire a "reload lexers" event is trivial and 100% safe.

The user should not touch the XML file where the lexers and relative associations are stored, but just the table in C::B. The modifications are then stored by C::B. But if this might make problems, better a 100% safe solution as "reload lexers" :).

Best wishes,
Michael

takeshimiya

  • Guest
Re: lexer file loading ...
« Reply #14 on: April 05, 2006, 03:46:44 pm »
Quote
TinyXML parsing is slow, with a rough measure of 200ms each lexer. [...]
SciTE loads way more lexers than C::B. The SciTE lexers also have more features.
You're comparing apples and oranges again. SciTE lexers have a collection of single line key/value pairs, and Code::Blocks lexers are xml documents that are validated for well-formedness. Of course it takes time to validate a document, this is not surprising.
Of course it's not surprising, and of course I'm comparing apples to oranges... Because they're different formats.
But that was a point.
Notice that those rough 200ms per xml lexer is on local disk, guess what takes to parse more than 50 C::B xml lexers.

The same goes for your network load story. You're missing the point here, too.
We are making on the order of 13,000 isolated file accesses during a "normal" startup. On a local file system, much of this can be cached, but it is absolutely not surprising that this is a major performance bottleneck over a network.
Yes, that's another point, further improvements can be done with caching,

wxWidgets makes on the order of 10,000 distinct file accesses alone to load the XRC files.
I thought that the XRC's were loaded from the zips, which then were read from memory instead of disk.
(zip's from disk, xrc's from memory, uncompressed).

To get back to TinyXML which is so terribly slow: the configuration file loads with about 6-7 file accesses, and all lexers are loaded using about 100 distinct file accesses. The time that TinyXML takes to parse those files is just ridiculous compared to the network latency of 10k accesses...
True, but if network latency were the only issue, why the SciTE lexers takes 1 second on LAN, while it haves more lexers?
What is SciTE doing <somehow> that reduces network latency? Perhaps what Michael suggested?


Revision 2306 has fixed the delay when opening "Settings->Editor". That's a start ;).
Great :D