The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



"Отказаться от UTF-8"
Версия для распечатки Пред. тема | След. тема
Форум Открытые системы на сервере
Исходное сообщение [ Отслеживать ]
Подсказка: Доступны два режима работы форума: "Раскрыть нити" и "Свернуть нити".
. "Отказаться от UTF-8: memcpy()" +2 +/
Сообщение от Sergey Maslennikov (ok), 23-Авг-17, 17:04 
> Посмотрите memcpy().

Неправильно я ответил. Смысл посмотреть на memcpy() есть, если предположить, что кто-то решился бы копировать внутри программ однобайтно-кодированную кириллицу. В этом случае копирование произошло бы примерно в 1.75 раза быстрее, чем копирование того же текста в UTF-8 [1].

Функция memcpy() может быть по разному реализована, но в реализациях, которые я видел, ожидаемое время копирования должно быть пропорционально размеру копируемых данных. В UTF-8 текст в 1.75 раза длиннее, чем в KOI8-R -- вот и копирует memcpy() его во столько же раз дольше. Это же соотношение можно получить экспериментально [2].

Возможно, я не уловил суть или цель совета использовать memcpy() при оптимизации путём выбора кодировки.

Ссылки / сноски:
[1] -- если копировать тот же текст, что упомянут в исходном посте;
[2] Экспериментальная программка -- обёртка, которую я собираюсь изредка применять для тестирования функций ICU. Здесь в качестве примера тестируемой функции я вставил memcpy():

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <unicode/utypes.h>
#include <unicode/ucnv.h>

long delta_t(struct timespec *start, struct timespec *end)
{
    time_t sec; long nsec;
    if ((end->tv_nsec-start->tv_nsec)<0) {
        sec = end->tv_sec-start->tv_sec-1;
        nsec = 1000000000+end->tv_nsec-start->tv_nsec;
    } else {
        sec = end->tv_sec-start->tv_sec;
        nsec = end->tv_nsec-start->tv_nsec;
    }
    return sec * 1000000000l + nsec;
}

int main()
{
  const char fnm_initial[] = "../../anna-karenina";
  FILE *fini = fopen(fnm_initial, "r");
  if (fini == NULL) {
    fprintf(stderr, "Can't open initial file.\n");
    return -1;
  }
  fseek(fini, 0L, SEEK_END);
  unsigned long len = ftell(fini), size = len + 1ul;
  fseek(fini, 0L, SEEK_SET);
  printf("Allocate %lu bytes to copy file \"%s\" ... ", size, fnm_initial); fflush(stdout);
  char *text_koi8 = malloc(size);
  if (text_koi8 == NULL) {
    fclose(fini);
    fprintf(stderr, "Can't allocate memory for \"text_koi8\".\n");
    return -2;
  }
  printf("Done.\n"); fflush(stdout); /* Allocated */
  if(fread(text_koi8, 1ul, len, fini) != len) {
    free(text_koi8);
    fclose(fini);
    fprintf(stderr, "Can't read file \"%s\" into the buffer.\n", fnm_initial);
    return -3;
  }
  fclose(fini);
  text_koi8[len] = '\x0';
  UErrorCode uerr = U_ZERO_ERROR;
  /* Here it is the example of the UTF-8 buffer exact size evaluation. It is however faster
     to allocate 2 * len + 1ul long buffer instaed and shrink it, after converting,
     by realloc() to the value returned by ucnv_convert(). */
  unsigned long size_u8 = ucnv_convert("UTF-8", "KOI8-R", NULL, 0ul, text_koi8, size, &uerr);
  if( uerr != U_BUFFER_OVERFLOW_ERROR &&
      uerr != U_STRING_NOT_TERMINATED_WARNING &&
      U_FAILURE(uerr) ) {
    free(text_koi8);
    fclose(fini);
    fprintf(stderr, "Can't evaluate UTF-8 text buffer size.\n");
    return -4;
  }
  printf("UTF-8 text buffer size = %lu bytes.\n", size_u8);
  char *text_utf8 = malloc(size_u8);
  if( text_koi8 == NULL ) {
    free(text_koi8);
    fclose(fini);
    fprintf(stderr, "Can't allocate memory for text_utf8.\n");
    return -5;
  }
  uerr = U_ZERO_ERROR;
  ucnv_convert("UTF-8", "KOI8-R", text_utf8, size_u8, text_koi8, size, &uerr);
  if( U_FAILURE(uerr) ) {
    free(text_utf8); free(text_koi8);
    fclose(fini);
    fprintf(stderr, "Error converting KOI8-R text into UTF-8 text.\n");
    return -6;
  }
  /* At this point we have two buffers with the same text in koi8-r and utf-8. */
  /* Prepare for measurements */
  char *text_koi8_a = malloc(size);
  if( text_koi8_a == NULL ) {
    free(text_utf8); free(text_koi8); fclose(fini);
    fprintf(stderr, " Can't allocate memory for \"text_koi8_a\".\n");
    return -7;
  }
  char *text_utf8_a = malloc(size_u8);
  if( text_utf8_a == NULL ) {
    free(text_koi8_a); free(text_utf8); free(text_koi8); fclose(fini);
    fprintf(stderr, "Can't allocate memory for \"text_utf8_a\".\n");
    return -8;
  }
  /* Buffers to copy into are ready here. */
  unsigned long i;
  struct timespec t0, t1;
  long Dt_call, Dt_koi8, Dt_utf8,
       Dt_koi8_total = 0ul, Dt_utf8_total = 0ul;
  double Dt_utf8_to_Dt_koi8;
  for(i = 0; i < 220ul; i++) {
    printf("------------- i = %lu -------------\n", i);
    /* Estimation of time for the function call itself (with copying
       negligibly small amount of data -- 1 byte) */
    clock_gettime(CLOCK_MONOTONIC, &t0);
    memcpy(text_koi8_a, text_koi8, 1ul);
    clock_gettime(CLOCK_MONOTONIC, &t1);
    Dt_call = delta_t(&t0, &t1); /* (in nanoseconds) */
    printf("Dt_call = %ld ns\n", Dt_call);
    /* Test for koi8-r */
    clock_gettime(CLOCK_MONOTONIC, &t0);
    memcpy(text_koi8_a, text_koi8, size);
    clock_gettime(CLOCK_MONOTONIC, &t1);
    Dt_koi8 = delta_t(&t0, &t1) - Dt_call;
    printf("Dt_koi8 = %ld ns\n", Dt_koi8); fflush(stdout);
    /* Test for utf-8 */
    clock_gettime(CLOCK_MONOTONIC, &t0);
    memcpy(text_utf8_a, text_utf8, size_u8);
    clock_gettime(CLOCK_MONOTONIC, &t1);
    Dt_utf8 = delta_t(&t0, &t1) - Dt_call;
    if (i > 9ul) { /* Skip first 10 experiments (wait for stabilization) */
      Dt_koi8_total += Dt_koi8;
      Dt_utf8_total += Dt_utf8;
    }
    printf("Dt_utf8 = %ld ns\n", Dt_utf8);
    Dt_utf8_to_Dt_koi8 = (double)Dt_utf8 / (double)Dt_koi8;
    printf("Dt_utf8 / Dt_koi8 = %.5g\n", Dt_utf8_to_Dt_koi8);
    fflush(stdout);
  }
  puts("===================================");
  printf("Dt_koi8_total = %ld ns\nDt_utf8_total = %ld ns\n"
         "Dt_utf8_total / Dt_koi8_total = %.5g\n",
         Dt_koi8_total, Dt_utf8_total,
         (double)Dt_utf8_total / (double)Dt_koi8_total);
  printf("len_u8 / len = %.5g\n", (double)(size_u8 - 1ul) / (double)len );
  free(text_utf8_a);
  free(text_koi8_a);
  free(text_utf8);
  free(text_koi8);
  return 0;
}

Ответить | Правка | Наверх | Cообщить модератору

Оглавление
Отказаться от UTF-8, Sergey Maslennikov, 06-Авг-17, 16:51  [смотреть все]
Форумы | Темы | Пред. тема | След. тема



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру