Model checking: use date instead of MD5 to improve the performance

Change from MD5 to internal attribute
Calculating MD5 is computationally/time expensive, so switch to using an attribute in the *.model.xml instead of calculating MD5.

See comments here:
c64b81e3a3 (commitcomment-171869728)

Close #17263
This commit is contained in:
PeterCJ 2025-12-03 10:09:48 -08:00 committed by Don HO
parent 2048d09086
commit 90aab8e041
5 changed files with 29 additions and 26 deletions

View File

@ -54,6 +54,7 @@
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>
<xs:attribute name="modelDate" type="xs:integer" use="optional"/>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:schema> </xs:schema>

View File

@ -97,6 +97,7 @@
</xs:unique> </xs:unique>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>
<xs:attribute name="modelDate" type="xs:integer" use="optional"/>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:schema> </xs:schema>

View File

@ -25,7 +25,6 @@
#include "UserDefineDialog.h" #include "UserDefineDialog.h"
#include "Notepad_plus_Window.h" #include "Notepad_plus_Window.h"
#include "NppConstants.h" #include "NppConstants.h"
#include "md5.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable : 4996) // for GetVersionEx() #pragma warning(disable : 4996) // for GetVersionEx()
@ -2003,31 +2002,34 @@ void NppParameters::updateFromModelXml(TiXmlNode* rootUser, ConfXml whichConf)
return; return;
} }
// now that the model is reasonable, it's reasonable to do the MD5-checking // compare the *.model.xml's modelDate to that of the active XML
MD5 md5; const wchar_t* wc_model_modelDate = rootModel->Attribute(L"modelDate");
std::string md5digest_model = md5.digestFile(sModelPath.c_str());
std::wstring wsDigest = string2wstring(md5digest_model, CP_UTF8);
std::string sUserText;
pXmlDocument->Print(sUserText);
std::string md5digest_user_text_before = md5.digestString(sUserText.c_str());
// if modelMD5 is the same as the one seen in the XML, don't need to merge in the model...
TiXmlElement* peRootUser = rootUser->ToElement(); TiXmlElement* peRootUser = rootUser->ToElement();
const wchar_t* pwct_modelMD5 = peRootUser->Attribute(L"modelMD5"); const wchar_t* wc_user_modelDate = peRootUser->Attribute(L"modelDate");
std::string s_modelMD5_from_xml = wstring2string(pwct_modelMD5 ? pwct_modelMD5 : L"\n", CP_UTF8);
s_modelMD5_from_xml.pop_back(); // remove the NULL-terminator // if both attributes exist, compare the integers to decide to exit if integer(user) >= integer(model),
if (md5digest_model == s_modelMD5_from_xml) // because then the user file is at least as new as the model, and doesn't need to be updated;
// if they don't both exist, need to do the update, because there aren't any dates to compare
if (wc_model_modelDate && wc_user_modelDate)
{
int v_model = decStrVal(wc_model_modelDate);
int v_user = decStrVal(wc_user_modelDate);
if (v_user >= v_model)
{ {
delete pXmlModel; delete pXmlModel;
return; return;
} }
}
// update (or add) the MD5 stored in the XML // get the current version of the text of the user file (used later to see if user file needs to be saved because of changes)
peRootUser->SetAttribute(L"modelMD5", wsDigest.c_str()); std::string sUserTextBefore;
pXmlDocument->Print(sUserTextBefore);
// update (or add) the modelDate stored in the active XML (unless it's missing)
if (wc_model_modelDate)
peRootUser->SetAttribute(L"modelDate", wc_model_modelDate);
// get the main internal <Languages> element from both user and model // get the main internal <Languages> element from both user and model
TiXmlElement* mainElemUser = rootUser->FirstChildElement(mainElementName); TiXmlElement* mainElemUser = rootUser->FirstChildElement(mainElementName);
TiXmlElement* mainElemModel = rootModel->FirstChildElement(mainElementName); TiXmlElement* mainElemModel = rootModel->FirstChildElement(mainElementName);
if (!mainElemUser || !mainElemModel) if (!mainElemUser || !mainElemModel)
@ -2051,10 +2053,9 @@ void NppParameters::updateFromModelXml(TiXmlNode* rootUser, ConfXml whichConf)
} }
// check the user-langs document for changes // check the user-langs document for changes
sUserText = ""; std::string sUserTextAfter;
pXmlDocument->Print(sUserText); pXmlDocument->Print(sUserTextAfter);
std::string md5digest_user_text_after = md5.digestString(sUserText.c_str()); if (sUserTextBefore != sUserTextAfter)
if (md5digest_user_text_before != md5digest_user_text_after)
{ {
switch (whichConf) switch (whichConf)
{ {

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<NotepadPlus> <NotepadPlus modelDate="20251203">
<!-- The keywords of the supported languages, don't touch them! --> <!-- The keywords of the supported languages, don't touch them! -->
<!-- For languages like C/C++ substyle1..8 entries, you may enter your own keywords in those entries, <!-- For languages like C/C++ substyle1..8 entries, you may enter your own keywords in those entries,
to have them show up in the "Default keywords" list shown in the Style Configurator --> to have them show up in the "Default keywords" list shown in the Style Configurator -->

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<NotepadPlus> <NotepadPlus modelDate="20251203">
<LexerStyles> <LexerStyles>
<LexerType name="actionscript" desc="ActionScript" ext=""> <LexerType name="actionscript" desc="ActionScript" ext="">
<WordsStyle name="DEFAULT" styleID="11" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" fontSize="" /> <WordsStyle name="DEFAULT" styleID="11" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" fontSize="" />