Pre-Unit conversion work refactor, replace category with categoryID (#1260)

Removed category as key in category to unit vector map and replaced with category id to reduce memory footprint.
This commit is contained in:
Quentin Al-Timimi 2020-06-04 10:51:06 -05:00 committed by GitHub
parent c7b0baaeda
commit 54d81721cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 37 additions and 48 deletions

View File

@ -109,7 +109,7 @@ CategorySelectionInitializer UnitConverter::SetCurrentCategory(const Category& i
{ {
if (m_currentCategory.id != input.id) if (m_currentCategory.id != input.id)
{ {
for (auto& unit : m_categoryToUnits[m_currentCategory]) for (auto& unit : m_categoryToUnits[m_currentCategory.id])
{ {
unit.isConversionSource = (unit.id == m_fromType.id); unit.isConversionSource = (unit.id == m_fromType.id);
unit.isConversionTarget = (unit.id == m_toType.id); unit.isConversionTarget = (unit.id == m_toType.id);
@ -121,7 +121,7 @@ CategorySelectionInitializer UnitConverter::SetCurrentCategory(const Category& i
} }
} }
newUnitList = m_categoryToUnits[input]; newUnitList = m_categoryToUnits[input.id];
} }
InitializeSelectedUnits(); InitializeSelectedUnits();
@ -283,7 +283,7 @@ void UnitConverter::RestoreUserPreferences(wstring_view userPreferences)
m_currentCategory = StringToCategory(outerTokens[2]); m_currentCategory = StringToCategory(outerTokens[2]);
// Only restore from the saved units if they are valid in the current available units. // Only restore from the saved units if they are valid in the current available units.
auto itr = m_categoryToUnits.find(m_currentCategory); auto itr = m_categoryToUnits.find(m_currentCategory.id);
if (itr != m_categoryToUnits.end()) if (itr != m_categoryToUnits.end())
{ {
const auto& curUnits = itr->second; const auto& curUnits = itr->second;
@ -713,10 +713,8 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
/// </summary> /// </summary>
void UnitConverter::ResetCategoriesAndRatios() void UnitConverter::ResetCategoriesAndRatios()
{ {
m_categories = m_dataLoader->LoadOrderedCategories();
m_switchedActive = false; m_switchedActive = false;
m_categories = m_dataLoader->GetOrderedCategories();
if (m_categories.empty()) if (m_categories.empty())
{ {
return; return;
@ -738,8 +736,8 @@ void UnitConverter::ResetCategoriesAndRatios()
continue; continue;
} }
vector<Unit> units = activeDataLoader->LoadOrderedUnits(category); vector<Unit> units = activeDataLoader->GetOrderedUnits(category);
m_categoryToUnits[category] = units; m_categoryToUnits[category.id] = units;
// Just because the units are empty, doesn't mean the user can't select this category, // Just because the units are empty, doesn't mean the user can't select this category,
// we just want to make sure we don't let an unready category be the default. // we just want to make sure we don't let an unready category be the default.
@ -789,7 +787,7 @@ void UnitConverter::InitializeSelectedUnits()
return; return;
} }
auto itr = m_categoryToUnits.find(m_currentCategory); auto itr = m_categoryToUnits.find(m_currentCategory.id);
if (itr == m_categoryToUnits.end()) if (itr == m_categoryToUnits.end())
{ {
return; return;

View File

@ -116,15 +116,6 @@ namespace UnitConversionManager
} }
}; };
class CategoryHash
{
public:
size_t operator()(const Category& x) const
{
return x.id;
}
};
struct SuggestedValueIntermediate struct SuggestedValueIntermediate
{ {
double magnitude; double magnitude;
@ -171,7 +162,7 @@ namespace UnitConversionManager
std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>, std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>,
UnitConversionManager::UnitHash> UnitConversionManager::UnitHash>
UnitToUnitToConversionDataMap; UnitToUnitToConversionDataMap;
typedef std::unordered_map<UnitConversionManager::Category, std::vector<UnitConversionManager::Unit>, UnitConversionManager::CategoryHash> typedef std::unordered_map<int, std::vector<UnitConversionManager::Unit>>
CategoryToUnitVectorMap; CategoryToUnitVectorMap;
class IViewModelCurrencyCallback class IViewModelCurrencyCallback
@ -190,8 +181,8 @@ namespace UnitConversionManager
public: public:
virtual ~IConverterDataLoader(){}; virtual ~IConverterDataLoader(){};
virtual void LoadData() = 0; // prepare data if necessary before calling other functions virtual void LoadData() = 0; // prepare data if necessary before calling other functions
virtual std::vector<Category> LoadOrderedCategories() = 0; virtual std::vector<Category> GetOrderedCategories() = 0;
virtual std::vector<Unit> LoadOrderedUnits(const Category& c) = 0; virtual std::vector<Unit> GetOrderedUnits(const Category& c) = 0;
virtual std::unordered_map<Unit, ConversionData, UnitHash> LoadOrderedRatios(const Unit& u) = 0; virtual std::unordered_map<Unit, ConversionData, UnitHash> LoadOrderedRatios(const Unit& u) = 0;
virtual bool SupportsCategory(const Category& target) = 0; virtual bool SupportsCategory(const Category& target) = 0;
}; };

View File

@ -220,14 +220,14 @@ void CurrencyDataLoader::LoadData()
}; };
#pragma optimize("", on) #pragma optimize("", on)
vector<UCM::Category> CurrencyDataLoader::LoadOrderedCategories() vector<UCM::Category> CurrencyDataLoader::GetOrderedCategories()
{ {
// This function should not be called // This function should not be called
// The model will use the categories from UnitConverterDataLoader // The model will use the categories from UnitConverterDataLoader
return vector<UCM::Category>(); return vector<UCM::Category>();
} }
vector<UCM::Unit> CurrencyDataLoader::LoadOrderedUnits(const UCM::Category& /*category*/) vector<UCM::Unit> CurrencyDataLoader::GetOrderedUnits(const UCM::Category& /*category*/)
{ {
lock_guard<mutex> lock(m_currencyUnitsMutex); lock_guard<mutex> lock(m_currencyUnitsMutex);
return m_currencyUnits; return m_currencyUnits;

View File

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. // Licensed under the MIT License.
#pragma once #pragma once
@ -63,8 +63,8 @@ namespace CalculatorApp
// IConverterDataLoader // IConverterDataLoader
void LoadData() override; void LoadData() override;
std::vector<UCM::Category> LoadOrderedCategories() override; std::vector<UCM::Category> GetOrderedCategories() override;
std::vector<UCM::Unit> LoadOrderedUnits(const UCM::Category& category) override; std::vector<UCM::Unit> GetOrderedUnits(const UCM::Category& category) override;
std::unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash> LoadOrderedRatios(const UCM::Unit& unit) override; std::unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash> LoadOrderedRatios(const UCM::Unit& unit) override;
bool SupportsCategory(const UnitConversionManager::Category& target) override; bool SupportsCategory(const UnitConversionManager::Category& target) override;
// IConverterDataLoader // IConverterDataLoader

View File

@ -22,18 +22,18 @@ UnitConverterDataLoader::UnitConverterDataLoader(GeographicRegion ^ region)
: m_currentRegionCode(region->CodeTwoLetter) : m_currentRegionCode(region->CodeTwoLetter)
{ {
m_categoryList = make_shared<vector<UCM::Category>>(); m_categoryList = make_shared<vector<UCM::Category>>();
m_categoryToUnits = make_shared<UCM::CategoryToUnitVectorMap>(); m_categoryIDToUnitsMap = make_shared<UCM::CategoryToUnitVectorMap>();
m_ratioMap = make_shared<UCM::UnitToUnitToConversionDataMap>(); m_ratioMap = make_shared<UCM::UnitToUnitToConversionDataMap>();
} }
vector<UCM::Category> UnitConverterDataLoader::LoadOrderedCategories() vector<UCM::Category> UnitConverterDataLoader::GetOrderedCategories()
{ {
return *m_categoryList; return *m_categoryList;
} }
vector<UCM::Unit> UnitConverterDataLoader::LoadOrderedUnits(const UCM::Category& category) vector<UCM::Unit> UnitConverterDataLoader::GetOrderedUnits(const UCM::Category& category)
{ {
return m_categoryToUnits->at(category); return this->m_categoryIDToUnitsMap->at(category.id);
} }
unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash> UnitConverterDataLoader::LoadOrderedRatios(const UCM::Unit& unit) unordered_map<UCM::Unit, UCM::ConversionData, UCM::UnitHash> UnitConverterDataLoader::LoadOrderedRatios(const UCM::Unit& unit)
@ -75,8 +75,8 @@ void UnitConverterDataLoader::LoadData()
GetConversionData(categoryToUnitConversionDataMap); GetConversionData(categoryToUnitConversionDataMap);
GetExplicitConversionData(explicitConversionData); // This is needed for temperature conversions GetExplicitConversionData(explicitConversionData); // This is needed for temperature conversions
m_categoryToUnits->clear(); this->m_categoryIDToUnitsMap->clear();
m_ratioMap->clear(); this->m_ratioMap->clear();
for (UCM::Category objectCategory : *m_categoryList) for (UCM::Category objectCategory : *m_categoryList)
{ {
ViewMode categoryViewMode = NavCategory::Deserialize(objectCategory.id); ViewMode categoryViewMode = NavCategory::Deserialize(objectCategory.id);
@ -86,7 +86,7 @@ void UnitConverterDataLoader::LoadData()
// Currency is an ordered category but we do not want to process it here // Currency is an ordered category but we do not want to process it here
// because this function is not thread-safe and currency data is asynchronously // because this function is not thread-safe and currency data is asynchronously
// loaded. // loaded.
m_categoryToUnits->insert(pair<UCM::Category, std::vector<UCM::Unit>>(objectCategory, {})); this->m_categoryIDToUnitsMap->insert(pair<int, std::vector<UCM::Unit>>(objectCategory.id, {}));
continue; continue;
} }
@ -103,7 +103,7 @@ void UnitConverterDataLoader::LoadData()
} }
// Save units per category // Save units per category
m_categoryToUnits->insert(pair<UCM::Category, std::vector<UCM::Unit>>(objectCategory, unitList)); this->m_categoryIDToUnitsMap->insert(pair<int, std::vector<UCM::Unit>>(objectCategory.id, unitList));
// For each unit, populate the conversion data // For each unit, populate the conversion data
for (UCM::Unit unit : unitList) for (UCM::Unit unit : unitList)

View File

@ -71,8 +71,8 @@ namespace CalculatorApp
private: private:
// IConverterDataLoader // IConverterDataLoader
void LoadData() override; void LoadData() override;
std::vector<UnitConversionManager::Category> LoadOrderedCategories() override; std::vector<UnitConversionManager::Category> GetOrderedCategories() override;
std::vector<UnitConversionManager::Unit> LoadOrderedUnits(const UnitConversionManager::Category& c) override; std::vector<UnitConversionManager::Unit> GetOrderedUnits(const UnitConversionManager::Category& c) override;
std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash> std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>
LoadOrderedRatios(const UnitConversionManager::Unit& unit) override; LoadOrderedRatios(const UnitConversionManager::Unit& unit) override;
bool SupportsCategory(const UnitConversionManager::Category& target) override; bool SupportsCategory(const UnitConversionManager::Category& target) override;
@ -87,7 +87,7 @@ namespace CalculatorApp
std::wstring GetLocalizedStringName(_In_ Platform::String ^ stringId); std::wstring GetLocalizedStringName(_In_ Platform::String ^ stringId);
std::shared_ptr<std::vector<UnitConversionManager::Category>> m_categoryList; std::shared_ptr<std::vector<UnitConversionManager::Category>> m_categoryList;
std::shared_ptr<UnitConversionManager::CategoryToUnitVectorMap> m_categoryToUnits; std::shared_ptr<UnitConversionManager::CategoryToUnitVectorMap> m_categoryIDToUnitsMap;
std::shared_ptr<UnitConversionManager::UnitToUnitToConversionDataMap> m_ratioMap; std::shared_ptr<UnitConversionManager::UnitToUnitToConversionDataMap> m_ratioMap;
Platform::String ^ m_currentRegionCode; Platform::String ^ m_currentRegionCode;
}; };

View File

@ -404,7 +404,7 @@ TEST_METHOD(Loaded_LoadOrderedUnits)
VERIFY_IS_TRUE(loader.LoadedFromCache()); VERIFY_IS_TRUE(loader.LoadedFromCache());
VERIFY_IS_FALSE(loader.LoadedFromWeb()); VERIFY_IS_FALSE(loader.LoadedFromWeb());
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY); vector<UCM::Unit> unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY);
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); const UCM::Unit usdUnit = GetUnit(unitList, L"USD");
@ -434,7 +434,7 @@ TEST_METHOD(Loaded_LoadOrderedRatios)
VERIFY_IS_TRUE(loader.LoadedFromCache()); VERIFY_IS_TRUE(loader.LoadedFromCache());
VERIFY_IS_FALSE(loader.LoadedFromWeb()); VERIFY_IS_FALSE(loader.LoadedFromWeb());
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY); vector<UCM::Unit> unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY);
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); const UCM::Unit usdUnit = GetUnit(unitList, L"USD");
@ -467,7 +467,7 @@ TEST_METHOD(Loaded_GetCurrencySymbols_Valid)
VERIFY_IS_TRUE(loader.LoadedFromCache()); VERIFY_IS_TRUE(loader.LoadedFromCache());
VERIFY_IS_FALSE(loader.LoadedFromWeb()); VERIFY_IS_FALSE(loader.LoadedFromWeb());
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY); vector<UCM::Unit> unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY);
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); const UCM::Unit usdUnit = GetUnit(unitList, L"USD");
@ -506,7 +506,7 @@ TEST_METHOD(Loaded_GetCurrencySymbols_Invalid)
VERIFY_ARE_EQUAL(wstring(L""), wstring(symbols.second.c_str())); VERIFY_ARE_EQUAL(wstring(L""), wstring(symbols.second.c_str()));
// Verify that when only one unit is valid, both symbols return as empty string. // Verify that when only one unit is valid, both symbols return as empty string.
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY); vector<UCM::Unit> unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY);
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); const UCM::Unit usdUnit = GetUnit(unitList, L"USD");
@ -539,7 +539,7 @@ TEST_METHOD(Loaded_GetCurrencyRatioEquality_Valid)
VERIFY_IS_TRUE(loader.LoadedFromCache()); VERIFY_IS_TRUE(loader.LoadedFromCache());
VERIFY_IS_FALSE(loader.LoadedFromWeb()); VERIFY_IS_FALSE(loader.LoadedFromWeb());
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY); vector<UCM::Unit> unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY);
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); const UCM::Unit usdUnit = GetUnit(unitList, L"USD");
@ -577,7 +577,7 @@ TEST_METHOD(Loaded_GetCurrencyRatioEquality_Invalid)
VERIFY_ARE_EQUAL(wstring(L""), ratio.second); VERIFY_ARE_EQUAL(wstring(L""), ratio.second);
// Verify that when only one unit is valid, both symbols return as empty string. // Verify that when only one unit is valid, both symbols return as empty string.
vector<UCM::Unit> unitList = loader.LoadOrderedUnits(CURRENCY_CATEGORY); vector<UCM::Unit> unitList = loader.GetOrderedUnits(CURRENCY_CATEGORY);
VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size()); VERIFY_ARE_EQUAL(size_t{ 2 }, unitList.size());
const UCM::Unit usdUnit = GetUnit(unitList, L"USD"); const UCM::Unit usdUnit = GetUnit(unitList, L"USD");

View File

@ -60,8 +60,8 @@ namespace UnitConverterUnitTests
c2units.push_back(u3); c2units.push_back(u3);
c2units.push_back(u4); c2units.push_back(u4);
m_units[c1] = c1units; m_units[c1.id] = c1units;
m_units[c2] = c2units; m_units[c2.id] = c2units;
unordered_map<Unit, ConversionData, UnitHash> unit1Map = unordered_map<Unit, ConversionData, UnitHash>(); unordered_map<Unit, ConversionData, UnitHash> unit1Map = unordered_map<Unit, ConversionData, UnitHash>();
unordered_map<Unit, ConversionData, UnitHash> unit2Map = unordered_map<Unit, ConversionData, UnitHash>(); unordered_map<Unit, ConversionData, UnitHash> unit2Map = unordered_map<Unit, ConversionData, UnitHash>();
@ -99,14 +99,14 @@ namespace UnitConverterUnitTests
m_loadDataCallCount++; m_loadDataCallCount++;
} }
vector<Category> LoadOrderedCategories() vector<Category> GetOrderedCategories()
{ {
return m_categories; return m_categories;
} }
vector<Unit> LoadOrderedUnits(const Category& c) vector<Unit> GetOrderedUnits(const Category& category)
{ {
return m_units[c]; return m_units[category.id];
} }
unordered_map<Unit, ConversionData, UnitHash> LoadOrderedRatios(const Unit& u) unordered_map<Unit, ConversionData, UnitHash> LoadOrderedRatios(const Unit& u)