Skip to content

Commit

Permalink
GL,Audio: use plain old binary search for extension setup.
Browse files Browse the repository at this point in the history
Because the cost of hundreds of tiny allocations when filling a
std::unordered_map (and then the cache unfriendliness of the whole
thing) definitely overweights the potential speedup by searching in O(1)
instead of O(log n). Same approach is chosen in the upcoming Vulkan
wrapper, I just backported it here.

This strips about 8 kB off the Emscripten build.
  • Loading branch information
mosra committed Jun 22, 2020
1 parent 54c42df commit e2621fa
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 140 deletions.
28 changes: 11 additions & 17 deletions src/Magnum/Audio/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,10 @@

#include "Context.h"

#include <unordered_map>

#include <al.h>
#include <alc.h>
#include <cstring>

#include <algorithm>
#include <Corrade/Utility/Arguments.h>
#include <Corrade/Utility/Assert.h>
#include <Corrade/Utility/Debug.h>
Expand Down Expand Up @@ -270,18 +268,13 @@ bool Context::tryCreate(const Configuration& configuration) {
alcMakeContextCurrent(_context);
currentContext = this;

/* Add all extensions to a map for faster lookup */
std::unordered_map<std::string, Extension> extensionMap;
for(const Extension& extension: Extension::extensions())
extensionMap.emplace(extension.string(), extension);

/* Check for presence of extensions */
const std::vector<std::string> extensions = extensionStrings();
for(const std::string& extension: extensions) {
const auto found = extensionMap.find(extension);
if(found != extensionMap.end()) {
_supportedExtensions.push_back(found->second);
_extensionStatus.set(found->second.index(), true);
const auto found = std::lower_bound(std::begin(ExtensionList), std::end(ExtensionList), extension, [](const Extension& a, const std::string& b) { return a.string() < b; });
if(found != std::end(ExtensionList) && found->string() == extension) {
_supportedExtensions.push_back(*found);
_extensionStatus.set(found->index(), true);
}
}

Expand All @@ -298,19 +291,20 @@ bool Context::tryCreate(const Configuration& configuration) {
/* Disable extensions that are known and supported and print a message
for each */
for(auto&& extension: _disabledExtensionStrings) {
auto found = extensionMap.find(extension);
const auto found = std::lower_bound(std::begin(ExtensionList), std::end(ExtensionList), extension, [](const Extension& a, const std::string& b) { return a.string() < b; });
/* No error message here because some of the extensions could be
from Vulkan or OpenGL. That also means we print the header only
when we actually have something to say */
if(found == extensionMap.end()) continue;
if(found == std::end(ExtensionList) || found->string() != extension)
continue;

/* If the extension isn't supported in the first place, don't do
anything. If it is, set its status as unsupported but flip the
corresponding bit in the disabled bitmap so we know it is
supported and only got disabled */
if(!_extensionStatus[found->second.index()]) continue;
_extensionStatus.set(found->second.index(), false);
_disabledExtensions.set(found->second.index(), true);
if(!_extensionStatus[found->index()]) continue;
_extensionStatus.set(found->index(), false);
_disabledExtensions.set(found->index(), true);

if(!headerPrinted) {
Debug{output} << "Disabling extensions:";
Expand Down
Loading

0 comments on commit e2621fa

Please sign in to comment.