从直觉来看,应该是map高,因为通过索引来对比应该比反复的判断并jmp来的快,但事实上违反直觉的是,当少量的键值对查找时候,发现switch快了一倍多!!!
// justTestit.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <map>
#include <unordered_map>
#include <regex>
#include "MyTimer.h"
using namespace std;
using namespace oneapm;
inline std::string file_extension(const std::string &path) {
std::smatch m;
static auto re = std::regex("\\.([a-zA-Z0-9]+)$");
if (std::regex_search(path, m, re)) { return m[1].str(); }
return std::string();
}
inline constexpr unsigned int str2tag_core(const char *s, size_t l,
unsigned int h) {
return (l == 0) ? h
: str2tag_core(s + 1, l - 1,
(h * 33) ^ static_cast<unsigned char>(*s));
}
inline unsigned int str2tag(const std::string &s) {
return str2tag_core(s.data(), s.size(), 0);
}
namespace udl {
inline constexpr unsigned int operator"" _t(const char *s, size_t l) {
return str2tag_core(s, l, 0);
}
} // namespace udl
inline const char *
find_content_type(const std::string &ext) {
using udl::operator""_t;
switch (str2tag(ext)) {
default: return nullptr;
case "css"_t: return "text/css";
case "csv"_t: return "text/csv";
case "txt"_t: return "text/plain";
case "vtt"_t: return "text/vtt";
case "htm"_t:
case "html"_t: return "text/html";
case "apng"_t: return "image/apng";
case "avif"_t: return "image/avif";
case "bmp"_t: return "image/bmp";
case "gif"_t: return "image/gif";
case "png"_t: return "image/png";
case "svg"_t: return "image/svg+xml";
case "webp"_t: return "image/webp";
case "ico"_t: return "image/x-icon";
case "tif"_t: return "image/tiff";
case "tiff"_t: return "image/tiff";
case "jpg"_t:
case "jpeg"_t: return "image/jpeg";
case "mp4"_t: return "video/mp4";
case "mpeg"_t: return "video/mpeg";
case "webm"_t: return "video/webm";
case "mp3"_t: return "audio/mp3";
case "mpga"_t: return "audio/mpeg";
case "weba"_t: return "audio/webm";
case "wav"_t: return "audio/wave";
case "otf"_t: return "font/otf";
case "ttf"_t: return "font/ttf";
case "woff"_t: return "font/woff";
case "woff2"_t: return "font/woff2";
case "7z"_t: return "application/x-7z-compressed";
case "atom"_t: return "application/atom+xml";
case "pdf"_t: return "application/pdf";
case "js"_t:
case "mjs"_t: return "application/javascript";
case "json"_t: return "application/json";
case "rss"_t: return "application/rss+xml";
case "tar"_t: return "application/x-tar";
case "xht"_t:
case "xhtml"_t: return "application/xhtml+xml";
case "xslt"_t: return "application/xslt+xml";
case "xml"_t: return "application/xml";
case "gz"_t: return "application/gzip";
case "zip"_t: return "application/zip";
case "wasm"_t: return "application/wasm";
}
}
inline const char * find_content_type1(const std::string ext)
{
static std::unordered_map<std::string, std::string> tagMap =
{
{"css", "text/css"},
{"csv", "text/csv"},
{"htm", "text/html"},
{"html", "text/html"},
{"js", "text/javascript"},
{"mjs", "text/javascript"},
{"txt", "text/plain"},
{"vtt", "text/vtt"},
{"apng", "image/apng"},
{"avif", "image/avif"},
{"bmp", "image/bmp"},
{"gif", "image/gif"},
{"png", "image/png"},
{"svg", "image/svg+xml"},
{"webp", "image/webp"},
{"ico", "image/x-icon"},
{"tif", "image/tiff"},
{"tiff", "image/tiff"},
{"jpg", "image/jpeg"},
{"jpeg", "image/jpeg"},
{"mp4", "video/mp4"},
{"mpeg", "video/mpeg"},
{"webm", "video/webm"},
{"mp3", "audio/mp3"},
{"mpga", "audio/mpeg"},
{"weba", "audio/webm"},
{"wav", "audio/wave"},
{"otf", "font/otf"},
{"ttf", "font/ttf"},
{"woff", "font/woff"},
{"woff2", "font/woff2"},
{"7z", "application/x-7z-compressed"},
{"atom", "application/atom+xml"},
{"pdf", "application/pdf"},
{"json", "application/json"},
{"rss", "application/rss+xml"},
{"tar", "application/x-tar"},
{"xht", "application/xhtml+xml"},
{"xhtml", "application/xhtml+xml"},
{"xslt", "application/xslt+xml"},
{"xml", "application/xml"},
{"gz", "application/gzip"},
{"zip", "application/zip"},
{"wasm", "application/wasm"}
};
auto it = tagMap.find(ext);
if (it == tagMap.end())
{
return nullptr;
}
else
{
return it->second.c_str();
}
}
inline const char * find_content_type2(const std::string ext)
{
using udl::operator""_t;
static std::unordered_map<unsigned int, std::string> tagMap =
{
{"css"_t, "text/css"},
{"csv"_t, "text/csv"},
{"htm"_t, "text/html"},
{"html"_t, "text/html"},
{"js"_t, "text/javascript"},
{"mjs"_t, "text/javascript"},
{"txt"_t, "text/plain"},
{"vtt"_t, "text/vtt"},
{"apng"_t, "image/apng"},
{"avif"_t, "image/avif"},
{"bmp"_t, "image/bmp"},
{"gif"_t, "image/gif"},
{"png"_t, "image/png"},
{"svg"_t, "image/svg+xml"},
{"webp"_t, "image/webp"},
{"ico"_t, "image/x-icon"},
{"tif"_t, "image/tiff"},
{"tiff"_t, "image/tiff"},
{"jpg"_t, "image/jpeg"},
{"jpeg"_t, "image/jpeg"},
{"mp4"_t, "video/mp4"},
{"mpeg"_t, "video/mpeg"},
{"webm"_t, "video/webm"},
{"mp3"_t, "audio/mp3"},
{"mpga"_t, "audio/mpeg"},
{"weba"_t, "audio/webm"},
{"wav"_t, "audio/wave"},
{"otf"_t, "font/otf"},
{"ttf"_t, "font/ttf"},
{"woff"_t, "font/woff"},
{"woff2"_t, "font/woff2"},
{"7z"_t, "application/x-7z-compressed"},
{"atom"_t, "application/atom+xml"},
{"pdf"_t, "application/pdf"},
{"json"_t, "application/json"},
{"rss"_t, "application/rss+xml"},
{"tar"_t, "application/x-tar"},
{"xht"_t, "application/xhtml+xml"},
{"xhtml"_t, "application/xhtml+xml"},
{"xslt"_t, "application/xslt+xml"},
{"xml"_t, "application/xml"},
{"gz"_t, "application/gzip"},
{"zip"_t, "application/zip"},
{"wasm"_t, "application/wasm"}
};
unsigned int code = str2tag(ext);
auto it = tagMap.find(code);
if (it == tagMap.end())
{
return nullptr;
}
else
{
return it->second.c_str();
}
}
int main()
{
static std::map<std::string, std::string> tagMap1 =
{
{"css", "text/css"},
{"csv", "text/csv"},
{"htm", "text/html"},
{"html", "text/html"},
{"js", "text/javascript"},
{"mjs", "text/javascript"},
{"txt", "text/plain"},
{"vtt", "text/vtt"},
{"apng", "image/apng"},
{"avif", "image/avif"},
{"bmp", "image/bmp"},
{"gif", "image/gif"},
{"png", "image/png"},
{"svg", "image/svg+xml"},
{"webp", "image/webp"},
{"ico", "image/x-icon"},
{"tif", "image/tiff"},
{"tiff", "image/tiff"},
{"jpg", "image/jpeg"},
{"jpeg", "image/jpeg"},
{"mp4", "video/mp4"},
{"mpeg", "video/mpeg"},
{"webm", "video/webm"},
{"mp3", "audio/mp3"},
{"mpga", "audio/mpeg"},
{"weba", "audio/webm"},
{"wav", "audio/wave"},
{"otf", "font/otf"},
{"ttf", "font/ttf"},
{"woff", "font/woff"},
{"woff2", "font/woff2"},
{"7z", "application/x-7z-compressed"},
{"atom", "application/atom+xml"},
{"pdf", "application/pdf"},
{"json", "application/json"},
{"rss", "application/rss+xml"},
{"tar", "application/x-tar"},
{"xht", "application/xhtml+xml"},
{"xhtml", "application/xhtml+xml"},
{"xslt", "application/xslt+xml"},
{"xml", "application/xml"},
{"gz", "application/gzip"},
{"zip", "application/zip"},
{"wasm", "application/wasm"}
};
Timer timer;
timer.start();
for (int i=0; i<1000; i++)
for (auto it : tagMap1)
{
const char * data = find_content_type(it.first);
}
double delta = timer.stop_delta_ms();
std::cout << delta << endl;
timer.start();
for (int i = 0; i < 1000; i++)
for (auto it : tagMap1)
{
const char * data = find_content_type1(it.first);
}
delta = timer.stop_delta_ms();
std::cout << delta << endl;
timer.start();
for (int i = 0; i < 1000; i++)
for (auto it : tagMap1)
{
const char * data = find_content_type2(it.first);
}
delta = timer.stop_delta_ms();
std::cout << delta << endl;
}
0.7367 // swith case
2.3099 // string map
2.1375 // int map