मैं अपने कुछ पुराने (और विशेष रूप से Win32 उन्मुख) सामानों को देख रहा हूं और इसे अधिक आधुनिक/पोर्टेबल बनाने के बारे में सोच रहा हूं - यानी सी ++ 11 में कुछ व्यापक रूप से पुन: प्रयोज्य भागों को पुन: कार्यान्वित करना। इन भागों में से एक utf8 और utf16 के बीच कनवर्ट है। Win32 एपीआई में मैं MultiByteToWideChar
/WideCharToMultiByte
का उपयोग कर रहा हूं, उस सामग्री को सी ++ 11 में नमूना कोड का उपयोग करके पोर्ट को बंद करने का प्रयास कर रहा हूं: https://stackoverflow.com/a/14809553। वहाँ कुछ कोड के साथ गलत है - परिणामutf8 <-> utf16: codecvt खराब प्रदर्शन
रिलीज निर्माण (, MSVS 2013 तक संकलित कोर i7 3610QM पर चलने)
stdlib = 1587.2 ms
Win32 = 127.2 ms
डीबग निर्माण
stdlib = 5733.8 ms
Win32 = 127.2 ms
सवाल है ? अगर सब कुछ ठीक लगता है - क्या इस तरह के प्रदर्शन अंतर के लिए कुछ अच्छा कारण है?
टेस्ट कोड के नीचे है:
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <clocale>
#include <codecvt>
#define XU_BEGIN_TIMER(NAME) \
{ \
LARGE_INTEGER __freq; \
LARGE_INTEGER __t0; \
LARGE_INTEGER __t1; \
double __tms; \
const char* __tname = NAME; \
char __tbuf[0xff]; \
\
QueryPerformanceFrequency(&__freq); \
QueryPerformanceCounter(&__t0);
#define XU_END_TIMER() \
QueryPerformanceCounter(&__t1); \
__tms = (__t1.QuadPart - __t0.QuadPart) * 1000.0/__freq.QuadPart; \
sprintf_s(__tbuf, sizeof(__tbuf), " %-24s = %6.1f ms\n", __tname, __tms); \
OutputDebugStringA(__tbuf); \
printf(__tbuf); \
}
std::string read_utf8() {
std::ifstream infile("C:/temp/UTF-8-demo.txt");
std::string fileData((std::istreambuf_iterator<char>(infile)),
std::istreambuf_iterator<char>());
infile.close();
return fileData;
}
void testMethod() {
std::setlocale(LC_ALL, "en_US.UTF-8");
std::string source = read_utf8();
{
std::string utf8;
XU_BEGIN_TIMER("stdlib") {
for(int i = 0; i < 1000; i++) {
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert2utf16;
std::u16string utf16 = convert2utf16.from_bytes(source);
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert2utf8;
utf8 = convert2utf8.to_bytes(utf16);
}
} XU_END_TIMER();
FILE* output = fopen("c:\\temp\\utf8-std.dat", "wb");
fwrite(utf8.c_str(), 1, utf8.length(), output);
fclose(output);
}
char* utf8 = NULL;
int cchA = 0;
{
XU_BEGIN_TIMER("Win32") {
for(int i = 0; i < 1000; i++) {
WCHAR* utf16 = new WCHAR[source.length() + 1];
int cchW;
utf8 = new char[source.length() + 1];
cchW = MultiByteToWideChar(
CP_UTF8, 0, source.c_str(), source.length(),
utf16, source.length() + 1);
cchA = WideCharToMultiByte(
CP_UTF8, 0, utf16, cchW,
utf8, source.length() + 1, NULL, false);
delete[] utf16;
if(i != 999)
delete[] utf8;
}
} XU_END_TIMER();
FILE* output = fopen("c:\\temp\\utf8-win.dat", "wb");
fwrite(utf8, 1, cchA, output);
fclose(output);
delete[] utf8;
}
}
आपका Win32 कोड बफर को सही ढंग से आवंटित नहीं कर रहा है। यूटीएफ -8 और यूटीएफ -16 में उनके डेटा की लंबाई के बीच 1-से-1 संबंध नहीं है। आपको आवश्यक बफर आकार की गणना करने के लिए एक बार 'मल्टीबाइट टॉइडहायर'/'वाइडछारटो मल्टीबीटाइट' कॉल करना चाहिए, फिर बफर आवंटित करना चाहिए, फिर वास्तविक रूपांतरण करने के लिए फिर से कॉल करें। तो यह थोड़ा सा समय को प्रभावित करता है। –
Win32 चूंकि विस्टा एसएसई को आंतरिक प्रभाव से आंतरिक रूप से उपयोग करता है, कुछ बहुत कम यूटीएफ ट्रांसकोडर्स करते हैं। इसे हरा करना मुश्किल होगा। –
@ रेमी लेबेउ: हाँ, अगर मैं अतिरिक्त आवंटित नहीं करना चाहता (वास्तव में अस्थायी मेमोरी) मुझे मल्टीबाइट टॉवाइडर/वाइडरहर्टोमोल्टीबीट को एक और बार कॉल करने की आवश्यकता है - यह 127 * 2 = 250ms के आसपास कुछ के लिए win32 उपयोगकेस लाएगा। यह अभी भी stdlib से 6.5 गुना तेज है। –