C - 为什么固定大小的数组比动态分配的数组执行速度慢得多?

时间:2015-05-03 00:43:15

标签: c arrays malloc

我有一个超过4M行的csv,我将其加载到一个数组中。

csv:EURUSD,20010102,230100,0.9507,0.9507,0.9507,0.9507,4

此操作大约需要3.5分钟。

...

typedef struct Rates_t
{
  char open[7];
  char high[7];
  char low[7];
  char close[7];
} Rates_t;

void Substr(char *src, char **dst, int start, int length)
{
  char *ptr1 = *dst;
  char *ptr2 = src+start;

  int i;
  for (i = 0; i < length; i++)
  {
    *(ptr1 + i) = *(ptr2 + i);
  }
  (*dst)[length] = '\0';
}

void FillRates(char *tmp, char *price)
{
  Substr(tmp, &price, 0, 6);
}

bool BacktestServer()
{  
  ...

  Rates_t r = { {0}, {0}, {0}, {0} };
  Rates_t *rates = &r;
  rates = (Rates_t *) malloc(sizeof(Rates_t));

  FILE *f;
  if (!(f = fopen("EURUSD.txt", "r"))) {
    fprintf(stderr, "Unable to open 'EURUSD.txt' for reading.\n");
    exit(1);
  }

  ...

  while (fgets(line, 72, f))
  {
    tmp = line;

    for (skip = 0; skip < 3; skip++)
    {
      tmp = strchr(tmp, ',');
      tmp++;
    }

    sz += sizeof(Rates_t);
    rates = (Rates_t *) realloc(rates, sz);

    FillRates(tmp, rates[i].open);
    tmp = strchr(tmp, ',');
    tmp++;

    FillRates(tmp, rates[i].high);
    tmp = strchr(tmp, ',');
    tmp++;

    FillRates(tmp, rates[i].low);
    tmp = strchr(tmp, ',');
    tmp++;

    FillRates(tmp, rates[i].close);

    i++;

    free(line);
    line = NULL;
    line = (char *) malloc(72 * sizeof(char));
  }

  ...

}

这大约需要1分钟。

...

typedef struct Rates_t
{
  char *open;
  char *high;
  char *low;
  char *close;
} Rates_t;

void Substr(char *src, char **dst, int start, int length)
{
  char *ptr1 = *dst;
  char *ptr2 = src+start;

  int i;
  for (i = 0; i < length; i++)
  {
    *(ptr1 + i) = *(ptr2 + i);
  }
  (*dst)[length] = '\0';
}

void FillRates(char *tmp, char *price)
{
  Substr(tmp, &price, 0, 6);
}

bool BacktestServer()
{  
  ...    

  Rates_t r = { NULL, NULL, NULL, NULL };
  Rates_t *rates = &r;
  rates = (Rates_t *) malloc(sizeof(Rates_t));

  FILE *f;
  if (!(f = fopen("EURUSD.txt", "r"))) {
    fprintf(stderr, "Unable to open 'EURUSD.txt' for reading.\n");
    exit(1);
  }

  ...

  while (fgets(line, 72, f))
  {
    tmp = line;

    for (skip = 0; skip < 3; skip++)
    {
      tmp = strchr(tmp, ',');
      tmp++;
    }

    sz += sizeof(Rates_t);
    rates = (Rates_t *) realloc(rates, sz);

    rates[i].open = (char *) malloc(7 * sizeof(char));
    FillRates(tmp, rates[i].open);

    tmp = strchr(tmp, ',');
    tmp++;

    rates[i].high = (char *) malloc(7 * sizeof(char));
    FillRates(tmp, rates[i].high);

    tmp = strchr(tmp, ',');
    tmp++;

    rates[i].low = (char *) malloc(7 * sizeof(char));
    FillRates(tmp, rates[i].low);

    tmp = strchr(tmp, ',');
    tmp++;

    rates[i].close = (char *) malloc(7 * sizeof(char));
    FillRates(tmp, rates[i].close);

    i++;

    free(line);
    line = NULL;
    line = (char *) malloc(72 * sizeof(char));
  }

  ...

}

使用memcpy或snprintf,程序将持续几秒钟。

void Substr(char *src, char **dst, int start, int length)
{
  memcpy(*dst, src+start, length);
  (*dst)[length] = '\0';
}
void Substr(char *src, char **dst, int start, int length)
{
  snprintf(*dst, length + 1, "%s", src+start);
  (*dst)[length] = '\0';
}

从在线共识来看,静态数组应该比动态数组更快。如果有人需要更多信息,我会编辑相应的帖子。

更新:

我按照建议将分配增加到不是2但是4096我仍然得到动态数组版本相同的结果,大约一分钟或更短。静态阵列版本减少到大约2.75分钟。

初始分配:

int sz = 256 * sizeof(Rates_t);
rates = (Rates_t *) malloc(sz);

重新分配:

if (realloc_count == 256)
{
  sz += 256 * sizeof(Rates_t);
  rates = (Rates_t *) realloc(rates, sz);
  realloc_count = 0;
}
realloc_count++;

我使用的是64位Windows机器,但是我通过cygwin gcc编译了32位程序。另一方面,在VM中的64位Linux上,速度显然要小得多,但速度却相反。动态分配的版本比静态版本花费更长的时间。在Linux上,动态内存= ~20-30秒,静态= ~15秒。在Linux @ 1,2,256,4096或524,288上,速度几乎没有变化。当我在cygwin上将分配增加到524,288时,静态分配约为6秒,动态分配约为8秒。

1 个答案:

答案 0 :(得分:1)

我很惊讶它会产生很大的不同,但是因为你realloc()数组读取了每行数据,所以复制该数组的成本很可能是罪魁祸首。如果目标是32位计算机,则包含完整数组的rates结构的大小可能只是仅包含指针的Rates_t结构的两倍。

正如JS1在评论中提到的那样,预先适当地调整数组大小(或者如果你不知道它需要多大就重新分配更大的块)应该会使运行时差消失。