Performance of converting v8::String to CefString

Do not post support requests, bug reports or feature requests. Discuss CEF here. Non-CEF related discussion goes in General Discussion!

Performance of converting v8::String to CefString

Postby fddima » Sun Sep 18, 2011 7:53 am

Current implementation of convert V8 strings into CefString uses this code:
Code: Select all
// Convert a V8 string to a UTF8 string.
std::string GetString(v8::Handle<v8::String> str)
{
  // Allocate enough space for a worst-case conversion.
  int len = str->Utf8Length();
  char* buf = new char[len+1];
  str->WriteUtf8(buf, len+1);
  std::string ret(buf, len);
  delete [] buf;
  return ret;
}


This code works good, and simple and have good compatibility around UTF8/UTF16/WIDE CEF strings.

But this code can be enchanced to be much faster. For first, that it doing in usual cases (i.e. CefString var = GetString(v8_string)?
1. heap alloc buffer for UTF8 string.
2. encode v8 string to UTF8.
3. copy encoded string to std:string (+ heap alloc).
4. heap free (allocated on step 1)
5. CefString created from std:string.
5.1. heap alloc new UTF16 buffer.
5.2. encode UTF8->UTF16
5.3. heap free (allocated on step 3).
Note, that all heap operations like malloc/free, is relative slowly (if you use standard allocator). In this case we have 2 unnecessary heap allocs/free and 2 unnecessary string re-encodings (utf16->utf8, utf8->utf16).

What is wrong with this?
By default CefString is UTF16 encoded.
I do not use other platforms than windows at this moment, but no have any sense to encode chars differently than UTF16, it have good balance between support of national characters and space. In other side it very close to existing platforms and standards. .NET CLR defines char as UTF16. W3C DOM works only with UTF16 strings. JavaScript works only with UTF16 strings. V8, as i see, also do not use UTF8 strings internally, it uses UTF16 strings, so currently when CEF converts string do it in always as bad-case (two reencodings performed).

My proposal - is create GetCefString method which will return CefString directly (in fact this method it can't return CefString 'cause CefString can't passed by value in this case):
if CEF_STRING_TYPE_UTF16 or CEF_STRING_TYPE_WIDE (and wchar_t is utf16): then we allocate one UTF16 buffer (which will be attached to CefString), and use v8::String.Write method to write UTF16 chars.
if CEF_STRING_TYPE_UTF8: then we allocate one UTF8 buffer (which will be attached to CefString), and use v8::String.WriteUtf8 method to write UTF8 chars.
if CEF_STRING_TYPE_WIDE and wchar_t is UTF32: then we must do reencoding. May be better do it via UTF16 and not via UTF8. Or stay with default behavior for this case.

When it used often? When we call native method from v8 extension / jsbinding - we always convert function name. Of course it also happens when we get string value from v8value.

In my tests, when i do not do unnecessary reencodings, it boosts performance of call native functions up to 25%. I.e. in standard way i have 100Kcps, and when we do not do any reencodings - i got 125Kcps.

Any proposals?

EDIT: Of course V8 internally can store strings even in ascii, but in common case V8 know when and how own internal store can be converted to UTF16 or UTF8.
fddima
Master
 
Posts: 788
Joined: Tue Dec 07, 2010 6:10 am

Re: Performance of converting v8::String to CefString

Postby fddima » Sun Sep 18, 2011 11:42 am

Example, current usage:
Code: Select all
   CefString func_name =
       GetString(v8::Handle<v8::String>::Cast(args.Callee()->GetName()));


My proposal:
Code: Select all
  CefString func_name;
  ToCefString(func_name, v8::Handle<v8::String>::Cast(args.Callee()->GetName()));

i know it is little ugly, but we can't pass CefString as return value -> it this case it will be copied twice.

Code: Select all
void v8impl_string_utf16_dtor(char16* str) { delete [] str; }

// TODO: this code assumes that CEF uses UTF16
void ToCefString(CefString& out, v8::Handle<v8::String> str)
{
    int len = str->Length();
    char16* buf = new char16[len + 1];
    str->Write((uint16_t*)buf, 0, -1);

    out.ClearAndFree();
    cef_string_t* retws = out.GetWritableStruct();
    retws->str = buf;
    retws->length = len;
    retws->dtor = v8impl_string_utf16_dtor;
}


As for me better if CefString can be created and/or assigned from v8::Handle<v8::String>, but i don't know how implement it clear, 'cause cef headers are visible for other side.
Any comments?
fddima
Master
 
Posts: 788
Joined: Tue Dec 07, 2010 6:10 am


Return to CEF Discussion

Who is online

Users browsing this forum: Majestic-12 [Bot] and 165 guests