LINUX.ORG.RU

групповое программирование


0

0

я тут зюзекаунтер на сях наваял аля top.mail.ru , кто пропатчит до супермегасчетчика?? Т.к. эта собака на моем супермегасервере 
пентиум 90 с 32 мегами оперативы после 200-го юзера начинает сильно 
подтормаживать.... ну типа просто ради исскуства.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "gd.h"
#include "gdfontl.h"
#include "gdfonts.h"

#define HTML_DIR1 "/var/www/html/count/ip.txt"
#define MAX_WORDS 12000
#define MAX_WORD_LEN 14
#define MAX_SENTENCE_LEN (MAX_WORDS * MAX_WORD_LEN)

int tokenize();
int eliminate_duplicates();
int print_words();

int main(void) {
  char sentence[MAX_SENTENCE_LEN], words[MAX_WORDS * MAX_WORD_LEN];
  char *full_path1 = HTML_DIR1;
  gdImagePtr im;
  int bg_color,fore_color,num_words,num1,num2;
  FILE *fp = NULL;
  int access_count;
  char str1[10]; char str2[10];
  int i, k; 
  im = gdImageCreate(80, 18);
  bg_color = gdImageColorAllocate(im, 0, 0, 0);
  fore_color = gdImageColorAllocate(im, 255, 255, 255);
  fp = fopen(full_path1,"a");
  fprintf(fp,"%s ",getenv("REMOTE_ADDR"));
  fclose(fp);
  fp = fopen(full_path1,"r");
  fgets(sentence, MAX_SENTENCE_LEN, fp);
  fclose(fp);
  num_words = tokenize(sentence,words);
  num2=eliminate_duplicates(words,num_words);
  num1=print_words(words,num_words);

  sprintf(str1, "%d", num_words);
  sprintf(str2, "%d", num1);
  gdImageString(im, gdFontSmall, 2, 1, str1, fore_color);
  gdImageString(im, gdFontSmall, 60, 1, str2, fore_color);
  printf("Content-type: image/png\n\n");
  gdImagePng(im, stdout);
  gdImageDestroy(im);
  return 0;
}

int tokenize(char sentence[MAX_SENTENCE_LEN], char words[MAX_SENTENCE_LEN]){
  int i = 0;
  char separators[] = " ", *token;
  token = strtok(sentence,separators);
  while(token != 0){
    strcpy(&words[i * MAX_WORD_LEN],token);
    token = strtok(0,separators);
    ++i;
  }
  return i;
}

int eliminate_duplicates(char words[MAX_WORDS * MAX_WORD_LEN], int num_words){
  int i, j, e;e=0;
  for(i = 0; i < num_words; ++i){
    for(j = 0; j < num_words; ++j){
      if(j != i){
        if((words[i * MAX_WORD_LEN] != '\0') && (words[j * MAX_WORD_LEN] != '\0')){
          if(strstr(&words[j * MAX_WORD_LEN],&words[i * MAX_WORD_LEN]) != 0){
            words[j * MAX_WORD_LEN] = '\0';
            e++;
          }
        }
      }
    }
  }
  return e;
}

int print_words(char words[MAX_WORDS * MAX_WORD_LEN], int num_words){
  int i,k; k=0;
  for(i = 0; i < num_words; ++i){
    if(words[i * MAX_WORD_LEN] != '\0'){
//      printf("%s ",&words[i * MAX_WORD_LEN]);
      k++;
    }
  }
//  printf ("%d\n",k);
  return k;
}



Перемещено JB из Talks
☆☆

2JB зря перенес, меня тут счас просклоняют и проспрягают по полной программе, оный текст только для толксов годится

vilfred ☆☆
() автор топика

Предлагаю следующие исправления:

1. filename.c -> filename.cpp

2. char  words[MAX_WORDS * MAX_WORD_LEN]; -> std::map<std::string, int> words; (или, если на твоей платформе есть hash_map, используй его)

3. strcpy(&words[i * MAX_WORD_LEN],token); -> words.insert(std::pair(std::string(token), 1));

4.

- int eliminate_duplicates(char words[MAX_WORDS * MAX_WORD_LEN], int num_words){
-   int i, j, e;e=0;
-   for(i = 0; i < num_words; ++i){
-     for(j = 0; j < num_words; ++j){
-       if(j != i){
-         if((words[i * MAX_WORD_LEN] != '\0') && (words[j * MAX_WORD_LEN] != '\0')){
-           if(strstr(&words[j * MAX_WORD_LEN],&words[i * MAX_WORD_LEN]) != 0){
-             words[j * MAX_WORD_LEN] = '\0';
-             e++;
-           }
-         }
-       }
-     }
-   }
-   return e;
- }

5. num1=print_words(words,num_words); -> num1= words.size();

И будет тебе счатье :) Не надо жаловатся на C++, если не лень, можете сами RB дерево для хранения слов реализовать , тогда на C все можно оставить.

А так, твой вариант затрачивает время порядка O(num_words^2), а вариант с std::map-ом - будет кушать O(log2(num_words))

fmj
()
Ответ на: комментарий от fmj

Забыл сказать, с вас $30 (т.к. оплачивается минимум час) ;)

fmj
()
Ответ на: комментарий от fmj

Лучше избегать повторного открытия файла fp = fopen(full_path1,"a"); fprintf(fp,"%s ",getenv("REMOTE_ADDR")); fclose(fp); fp = fopen(full_path1,"r"); fgets(sentence, MAX_SENTENCE_LEN, fp); fclose(fp);

anonymous
()
Ответ на: комментарий от fmj

Лучше избегать повторного открытия файла 
  fp = fopen(full_path1,"a");
  fprintf(fp,"%s ",getenv("REMOTE_ADDR"));
  fclose(fp);
  fp = fopen(full_path1,"r");
  fgets(sentence, MAX_SENTENCE_LEN, fp);
  fclose(fp);

anonymous
()
Ответ на: комментарий от anonymous

int i = 0; char separators[] = " ", *token; token = strtok(sentence,separators); while(token != 0){ strcpy(&words[i * MAX_WORD_LEN],token); token = strtok(0,separators); ++i; }

по моему логичнее было-бы int i; char separators[] = " ", *token; token = strtok(sentence,separators); for (i=0, token != 0, i++) { .... }

anonymous
()
Ответ на: комментарий от anonymous

(уродское форматирование)

  int i = 0;
  char separators[] = " ", *token;
  token = strtok(sentence,separators);
  while(token != 0){
    strcpy(&words[i * MAX_WORD_LEN],token);
    token = strtok(0,separators);
    ++i;
  }


по моему логичнее было-бы
int i;
  char separators[] = " ", *token;
  token = strtok(sentence,separators);
for (i=0, token != 0, i++) {
....
}

anonymous
()
Ответ на: комментарий от anonymous

на сколько я понимаю у тебя прога тормозит из-за того что куча процессов пытаюстся писать в 1 файл одновременно. Что само по себе не есть гуд. Так что при увеличении одновременных запусков счетчика это будет тормозить все больше и больше.

anonymous
()
Ответ на: комментарий от fmj

Вообще же всяко в данной ситуации будем иметь проблему следующего плана: при каждом обращении мы будем повторно процессировать весь лог файл, что очень долго, в идеале нужно хранить уже на диске все в виде дерева, и обновлять каунтеры на диске. Т.е. усложнять надо ту часть, которая логгирует факт визита, и максимально упрощать ту, которая отображает число посещений.

fmj
()
Ответ на: комментарий от anonymous

> на сколько я понимаю у тебя прога тормозит из-за того что куча процессов пытаюстся писать в 1 файл одновременно. Что само по себе не есть гуд. Так что при увеличении одновременных запусков счетчика это будет тормозить все больше и больше.

Это тебя в каком классе этому научили? :)

fmj
()

> #define HTML_DIR1 "/var/www/html/count/ip.txt"

Выбор имен - супер. Чтоб враг не догадался -)

gods-little-toy ★★★
()

По поводу счетчика - это ужас. Все выкинуть и либо переписать ввиде демона либо скрипта юзающего какой-нибудь БД, можно псевдо-бд типа memcached. IP-адресов же много на свете... Или это счетчик для использования в пределах одной локалки?

Еще, ты-щь vilfred, удручает ваша манера постить голый код без описания чего это такое. Людям некогда ваши пьяные эскапады на C анализировать. В начале программы такого размера уместно 4х-5ти строчное описание чего/как она делает, на простом английском. Лицо, неспособное составить подобное описание признается тварью бессловесной, то есть жывотным. Остальные лица, написав такой обзор, сразу осознают бредовость идеи (например счетчик выбранной вами архитектуры и претензии на производительность), и благородно выбирают не захламлять мир ущербными сущностями.

gods-little-toy ★★★
()
Ответ на: комментарий от anonymous

> fmj, что не нравится?

А с чего собственно должна тормозить операция дописывания в конец файла в данном случае? Тормозит постпроцессинг, при котором он перечитывает файл каждый раз, и выкидывает дубликаты, это занимает время пропорциональное квадрату файла, т.е. если для 100 строчек, это 0.1с, то для 1000 это уже 10 секунд

fmj
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.