Commit a6c68c0
committed
Speedup parsing using regexps
Since the initial introduction of extendend parsing in 12e38b9 (regex
parsing, 2015-12-30) the speed of parsing the procedure files is not
good.
A quick check with FunctionProfiling reveals
Total time: 25.3811, Time in Function code: 18.0965 (71.3%)
Top function percentages:
Function CodeBrowser.ipf [CodeBrowserModule] addDecoratedConstants: 23%
Function CodeBrowser.ipf [CodeBrowserModule] addDecoratedMenu: 23%
Function CodeBrowser.ipf [CodeBrowserModule] addDecoratedStructure: 23%
Function CodeBrowser.ipf [CodeBrowserModule] addDecoratedMacros: 22%
Annotated Top Functions:
*******************************************************************************************
Function: CodeBrowser.ipf [CodeBrowserModule] addDecoratedConstants;
Percent total 23%
*******************************************************************************************
[00] |Function addDecoratedConstants(module,
procedureWithoutModule, declWave, lineWave)
[00] | String module, procedureWithoutModule
[00] | WAVE/T declWave
[00] | WAVE/D lineWave
[00] |
[00] | Variable numLines, i, idx, numEntries,
numMatches
[00] | String procText, re, def, name
[00] |
[00] | Wave/T helpWave = getHelpWave()
[00] |
[00] | // get procedure code
[00] | procText = getProcedureText("", 0, module,
procedureWithoutModule)
[00]* | numLines = ItemsInList(procText, "\r")
[00] |
[00] | // search code and return wavLineNumber
[22]** | Make/FREE/N=(numLines)/T text =
StringFromList(p, procText, "\r")
[00] | // help for regex on https://regex101.com/
[00] | re =
"^(?i)[[:space:]]*((?:override\s+)?(?:static)?[[:space:]]*(?:Str)?Constant)[[:space:]]+([^=\s]*)\s*=\s*(?:\"(?:[^\"\\\\]|\\\\.)+\"|0[xX][0-9a-fA-F]+|[0-9]+)\s*(?:[\/]{2}.*)?"
[00]* | Grep/Q/INDX/E=re text
[00] | Wave W_Index
[00]* | Duplicate/FREE W_Index wavLineNumber
[00]* | KillWaves/Z W_Index
[00] | KillStrings/Z S_fileName
[00] | WaveClear W_Index
[00] | if(!V_Value) // no matches
[00] | return 0
[00] | endif
[00] |
[00]* | numMatches = DimSize(wavLineNumber, 0)
[00] | numEntries = DimSize(declWave, 0)
[00]* | Redimension/N=(numEntries + numMatches, -1)
declWave, lineWave, helpWave
[00] |
[00] | idx = numEntries
[00]* | for(i = 0; i < numMatches; i += 1)
[00]* | SplitString/E=re text[wavLineNumber[i]],
def, name
[00] |
[00]* | declWave[idx][0] =
createMarkerForType(LowerStr(def))
[00] | declWave[idx][1] = name
[00] | lineWave[idx] = wavLineNumber[i]
[00] | idx += 1
[00] | endfor
[00] |
[00] | KillWaves/Z W_Index
[00] |End
*******************************************************************************************
Function: CodeBrowser.ipf [CodeBrowserModule] addDecoratedMenu; Percent
total 23%
*******************************************************************************************
[00] |Function addDecoratedMenu(module,
procedureWithoutModule, declWave, lineWave)
[00] | String module, procedureWithoutModule
[00] | WAVE/T declWave
[00] | WAVE/D lineWave
[00] |
[00] | Variable numLines, idx, numEntries, numMatches
[00] | String procText, re, def, name, type
[00] | String currentMenu = ""
[00] |
[00] | Wave/T helpWave = getHelpWave()
[00] |
[00] | // get procedure code
[00] | procText = getProcedureText("", 0, module,
procedureWithoutModule)
[00]* | numLines = ItemsInList(procText, "\r")
[00] |
[00] | // search code and return wavLineNumber
[23]** | Make/FREE/N=(numLines)/T text =
StringFromList(p, procText, "\r")
[00] | // regexp: match case insensitive (?i) spaces
don't matter. search for menu or submenu with a name in double quotes.
[00] | // help for regex on https://regex101.com/
[00] | re =
"^(?i)[[:space:]]*(menu|submenu)[[:space:]]+\"((?:[^\"\\\\]|\\\\.)+)\"(?:[[:space:]]*[,][[:space:]]*(hideable|dynamic|contextualmenu))?"
[00]* | Grep/Q/INDX/E=re text
[00] | numMatches = !!V_Value
[00] | Wave W_Index
[00]* | Duplicate/FREE W_Index wavLineNumber
[00]* | KillWaves/Z W_Index
[00]* | KillStrings/Z S_filename
[00] | if(!numMatches)
[00] | return 0
[00] | endif
[00] |
[00] | numMatches = DimSize(wavLineNumber, 0)
[00] | numEntries = DimSize(declWave, 0)
[00] | Redimension/N=(numEntries + numMatches, -1)
declWave, lineWave, helpWave
[00] |
[00] | for(idx = numEntries; idx < (numEntries +
numMatches); idx += 1)
[00]* | SplitString/E=re text[wavLineNumber[(idx
- numEntries)]], def, name, type
[00] | def = LowerStr(def)
[00] | if(!cmpstr(def, "menu"))
[00] | currentMenu = name
[00] | endif
[00] | declWave[idx][0] =
createMarkerForType(def)
[00] | declWave[idx][1] = "Menu " + currentMenu
[00] | if(!cmpstr(def, "submenu"))
[00] | declWave[idx][1] += ":" + name
[00] | endif
[00] | if(cmpstr(type, ""))
[00] | declWave[idx][1] += "(" + type +
")"
[00] | endif
[00] |
[00] | lineWave[idx] = wavLineNumber[(idx -
numEntries)]
[00] | endfor
[00] |End
*******************************************************************************************
Function: CodeBrowser.ipf [CodeBrowserModule] addDecoratedStructure;
Percent total 23%
*******************************************************************************************
[00] |Function addDecoratedStructure(module,
procedureWithoutModule, declWave, lineWave, [parseVariables])
[00] | String module, procedureWithoutModule
[00] | WAVE/T declWave
[00] | WAVE/D lineWave
[00] | Variable parseVariables
[00]* | if(paramIsDefault(parseVariables) |
parseVariables != 1)
[00] | parseVariables = 1 // added for
debugging
[00] | endif
[00] |
[00] | variable numLines, idx, numEntries, numMatches
[00] | string procText, reStart, reEnd, name,
StaticKeyword
[00] |
[00] | Wave/T helpWave = getHelpWave()
[00] |
[00] | // get procedure code
[00] | procText = getProcedureText("", 0, module,
procedureWithoutModule)
[00]* | numLines = ItemsInList(procText, "\r")
[00] | if(numLines == 0)
[00] | debugPrint("no Content in Procedure " +
procedureWithoutModule)
[00] | endif
[00] |
[00] | // search code and return wavLineNumber
[22]** | Make/FREE/N=(numLines)/T text =
StringFromList(p, procText, "\r")
[00] | // regexp: match case insensitive (?i) leading
spaces don't matter. optional static statement. search for structure
name which contains no spaces. followed by an optional space and nearly
anything like inline comments
[00] | // help for regex on https://regex101.com/
[00] | reStart =
"^(?i)[[:space:]]*((?:static[[:space:]])?)[[:space:]]*structure[[:space:]]+([^[:space:]\/]+)[[:space:]\/]?.*"
[00]* | Grep/Q/INDX/E=reStart text
[00] | Wave W_Index
[00]* | Duplicate/FREE W_Index wavStructureStart
[00]* | KillWaves/Z W_Index
[00]* | KillStrings/Z S_fileName
[00] | WaveClear W_Index
[00] | if(!V_Value) // no matches
[00] | return 0
[00] | endif
[00] | numMatches = DimSize(wavStructureStart, 0)
[00] |
[00] | // optionally analyze structure elements
[00] | if(parseVariables)
[00] | // regexp: match case insensitive
endstructure followed by (space or /) and anything else or just a
lineend
[00] | // does not match endstructure23 but
endstructure//
[00] | reEnd =
"^(?i)[[:space:]]*(?:endstructure(?:[[:space:]]|\/).*)|endstructure$"
[00]* | Grep/Q/INDX/E=reEnd text
[00] | Wave W_Index
[00]* | Duplicate/FREE W_Index wavStructureEnd
[00]* | KillWaves/Z W_Index
[00] | KillStrings/Z S_fileName
[00] | WaveClear W_Index
[00] | if(numMatches !=
DimSize(wavStructureEnd, 0))
[00] | numMatches = 0
[00] | return 0
[00] | endif
[00] | endif
[00] |
[00] | numEntries = DimSize(declWave, 0)
[00] | Redimension/N=(numEntries + numMatches, -1)
declWave, lineWave, helpWave
[00] |
[00] | for(idx = numEntries; idx < (numEntries +
numMatches); idx +=1)
[00]* | SplitString/E=reStart
text[wavStructureStart[(idx - numEntries)]], StaticKeyword, name
[00]* | declWave[idx][0] =
createMarkerForType(LowerStr(StaticKeyword) + "structure") // no " "
between static and structure needed
[00] | declWave[idx][1] = name
[00] |
[00] | // optionally parse structure elements
[00] | if(parseVariables)
[00] |
Duplicate/FREE/R=[(wavStructureStart[(idx -
numEntries)]),(wavStructureEnd[(idx - numEntries)])] text, temp
[00] | declWave[idx][1] +=
getStructureElements(temp)
[00] | WaveClear temp
[00] | endif
[00] |
[00]* | lineWave[idx] = wavStructureStart[(idx -
numEntries)]
[00] | endfor
[00] |
[00] | WaveClear wavStructureStart, wavStructureEnd
[00] |End
*******************************************************************************************
Function: CodeBrowser.ipf [CodeBrowserModule] addDecoratedMacros;
Percent total 22%
*******************************************************************************************
[00] |Function addDecoratedMacros(module,
procedureWithoutModule, declWave, lineWave)
[00] | String module, procedureWithoutModule
[00] | WAVE/T declWave
[00] | WAVE/D lineWave
[00] |
[00] | Variable numLines, idx, numEntries, numMatches
[00] | String procText, re, def, name, arguments, type
[00] |
[00] | Wave/T helpWave = getHelpWave()
[00] |
[00] | // get procedure code
[00]* | procText = getProcedureText("", 0, module,
procedureWithoutModule)
[00]* | numLines = ItemsInList(procText, "\r")
[00] |
[00] | // search code and return wavLineNumber
[22]** | Make/FREE/N=(numLines)/T text =
StringFromList(p, procText, "\r")
[00] | // regexp: match case insensitive (?i) spaces
don't matter. search for window or macro or proc. Macro Name is the the
next non-space character followed by brackets () where the arguments
are. At the end there might be a colon, specifying the type of macro and
a comment beginning with /
[00] | // macro should have no arguments. Handled for
backwards compatibility.
[00] | // help for regex on https://regex101.com/
[00] | re =
"^(?i)[[:space:]]*(window|macro|proc)[[:space:]]+([^[:space:]]+)[[:space:]]*\((.*)\)[[:space:]]*[:]?[[:space:]]*([^[:space:]\/]*).*"
[00]* | Grep/Q/INDX/E=re text
[00] | Wave W_Index
[00]* | Duplicate/FREE W_Index wavLineNumber
[00]* | KillWaves/Z W_Index
[00]* | KillStrings/Z S_fileName
[00] | WaveClear W_Index
[00] | if(!V_Value) // no matches
[00] | return 0
[00] | endif
[00] |
[00] | numMatches = DimSize(wavLineNumber, 0)
[00] | numEntries = DimSize(declWave, 0)
[00] | Redimension/N=(numEntries + numMatches, -1)
declWave, lineWave, helpWave
[00] |
[00] | for(idx = numEntries; idx < (numEntries +
numMatches); idx += 1)
[00]* | SplitString/E=re text[wavLineNumber[(idx
- numEntries)]], def, name, arguments, type
[00] | // def containts window/macro/proc
[00] | // type contains Panel/Layout for
subclasses of window macros
[00] | declWave[idx][0] =
createMarkerForType(LowerStr(def))
[00] | declWave[idx][1] = name + "(" +
trimArgument(arguments, ",", strListSepStringOutput = ", ") + ")" + " :
" + type
[00] | lineWave[idx] = wavLineNumber[(idx -
numEntries)]
[00] | endfor
[00] |End
So pulling out the procedure text conversion to list and do it only once
is a first obvious optimisation.
For IP7 and later the new function ListToTextWave is also used.
The parsing time for MIES_DAEphys.ipf dropped from 1.5s to 56ms.1 parent 3c1f33f commit a6c68c0
1 file changed
+39
-39
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
373 | 373 | | |
374 | 374 | | |
375 | 375 | | |
376 | | - | |
377 | | - | |
| 376 | + | |
| 377 | + | |
378 | 378 | | |
379 | 379 | | |
380 | 380 | | |
| |||
383 | 383 | | |
384 | 384 | | |
385 | 385 | | |
386 | | - | |
387 | | - | |
388 | | - | |
389 | | - | |
390 | | - | |
391 | | - | |
392 | 386 | | |
393 | 387 | | |
394 | 388 | | |
| |||
418 | 412 | | |
419 | 413 | | |
420 | 414 | | |
421 | | - | |
422 | | - | |
| 415 | + | |
| 416 | + | |
423 | 417 | | |
424 | 418 | | |
425 | 419 | | |
| |||
428 | 422 | | |
429 | 423 | | |
430 | 424 | | |
431 | | - | |
432 | | - | |
433 | | - | |
434 | | - | |
435 | | - | |
436 | | - | |
437 | 425 | | |
438 | 426 | | |
439 | 427 | | |
| |||
462 | 450 | | |
463 | 451 | | |
464 | 452 | | |
465 | | - | |
466 | | - | |
| 453 | + | |
| 454 | + | |
467 | 455 | | |
468 | 456 | | |
469 | 457 | | |
| |||
476 | 464 | | |
477 | 465 | | |
478 | 466 | | |
479 | | - | |
480 | | - | |
481 | | - | |
482 | | - | |
483 | | - | |
484 | | - | |
485 | | - | |
486 | | - | |
487 | | - | |
488 | 467 | | |
489 | 468 | | |
490 | 469 | | |
| |||
537 | 516 | | |
538 | 517 | | |
539 | 518 | | |
540 | | - | |
541 | | - | |
| 519 | + | |
| 520 | + | |
542 | 521 | | |
543 | 522 | | |
544 | 523 | | |
| |||
548 | 527 | | |
549 | 528 | | |
550 | 529 | | |
551 | | - | |
552 | | - | |
553 | | - | |
554 | | - | |
555 | | - | |
556 | | - | |
557 | 530 | | |
558 | 531 | | |
559 | 532 | | |
| |||
738 | 711 | | |
739 | 712 | | |
740 | 713 | | |
741 | | - | |
742 | | - | |
743 | | - | |
744 | | - | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
745 | 720 | | |
746 | 721 | | |
747 | 722 | | |
748 | 723 | | |
749 | 724 | | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
750 | 750 | | |
751 | 751 | | |
752 | 752 | | |
| |||
0 commit comments