Author Topic: Ускорение работы с файлом.  (Read 19211 times)

0 Members and 1 Guest are viewing this topic.

putman

  • Активный участник
  • ***
  • Posts: 199
    • View Profile
Ускорение работы с файлом.
« on: January 20, 2014, 05:41:17 PM »
И снова здравствуйте.
Моя программка на Мой мир, что на майл.ру, заходит в анкету, ставит "Нравится" и пишет в файл урл этой страницы, что бы повторно не заходить.
За 2 дня уже более 3000 анкет в файле, работа заметно замедлилась, т.к. перед входом в анкету в цикле файл открывается 3000 раз и проверяется очередная строка на повторение.
Хочу узнать, возможно сразу все строки из файла считать в массив, или переменную далее разделив (тут уже ограничение по длине переменной наверное не даст).
В памяти же писать допустим 50 страниц и скопом писать в файл, тем самым снизив число обращений к диску.
Диск у меня флешевый, думал будет быстро работать, но уже около секунды тратит на 3000 чтений. А когда будет 30 000 ...
Что посоветуете ?
Спасибо.

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Re: Ускорение работы с файлом.
« Reply #1 on: January 20, 2014, 06:56:17 PM »
Быстрее вряд ли выйдет

Вот считывание всех строк в массив. Это для 4.9 версии. Для 4.8 в место $n+1 надо писать $n
Code: (clickermann) [Select]
FOR($n,$n<TFCOUNT ("Файл.txt"))
   ARRPUSH($links, TFREAD ("Файл.txt", $n+1))
END_CYC
HALT

ограничение на строку 256 симолов. Здесь помогла бы функция поиска в файле или в массиве, еслиб она была.....

putman

  • Активный участник
  • ***
  • Posts: 199
    • View Profile
Re: Ускорение работы с файлом.
« Reply #2 on: January 23, 2014, 07:59:36 PM »
Cделал загрузку файла в массив.
Поиск идёт в массиве.
Особой разницы между сравнением каждой строки из файла не заметил.
Ощущение что массивы организованы в файлах )))

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Ускорение работы с файлом.
« Reply #3 on: January 23, 2014, 09:47:00 PM »
Наверно большой массив тоже нехило замедляет. А ну ворочать его.
Может стоит искать другой подход. Например, снижать количество сравниваемых символов. Сравнивать не весь урл, а только последнюю часть - параметр строки. Обычно анкеты, аккаунты так формируются. И в файл/массив тоже писать не весь.
Можно ещё что нибудь придумать. Может там деление по датам есть. На крайний случай проверку адреса с базой переложить на внешний модуль на другом языке/программе. Да вот хотя бы Ассемблер :)


putman

  • Активный участник
  • ***
  • Posts: 199
    • View Profile
Re: Ускорение работы с файлом.
« Reply #4 on: January 24, 2014, 05:43:30 PM »
... Сравнивать не весь урл, а только последнюю часть - параметр строки. Обычно анкеты, аккаунты так формируются. И в файл/массив тоже писать не весь.
Хорошая идея, тогда подскажите как лучше удалить начало урл  ?
Маска не одна и та же, их может быть три:

http://my.mail.ru/mail/
http://my.mail.ru/bk/
http://my.mail.ru/list/

Функция STRFILTER, поудаляет не только начало урл, но и все совпадающие с ними символы в значимой части.
Как посоветуете поступить ?




Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Ускорение работы с файлом.
« Reply #5 on: January 24, 2014, 06:16:33 PM »
Хорошая идея, тогда подскажите как лучше удалить начало урл  ?
Маска не одна и та же, их может быть три:

http://my.mail.ru/mail/
http://my.mail.ru/bk/
http://my.mail.ru/list/

Функция STRFILTER, поудаляет не только начало урл, но и все совпадающие с ними символы в значимой части.
Как посоветуете поступить ?
Аааа... на мэйле. Боюсь не поможет, там адреса и так короткие. Но можно попробовать.
С телефона, по памяти
$url = STRCUT2($url, POS("l/")+2, POS("/")-1)
$url = STRCUT2($url, POS("k/")+2, POS("/")-1)
$url = STRCUT2($url, POS("t/")+2, POS("/")-1)

Нужно пробовать, время мерять.
Можно попробовать в начале скрипта считать не в один массив, а несколько поменьше. Или считать в несколько текстовых переменных объединив стрконкатом. Потом искать подстроку в строке.
Аж интересно. Нужно тест сделать чтобы представлять порядок цифр.
« Last Edit: January 24, 2014, 06:23:03 PM by Vint »


putman

  • Активный участник
  • ***
  • Posts: 199
    • View Profile
Re: Ускорение работы с файлом.
« Reply #6 on: January 24, 2014, 07:00:42 PM »
У меня 4 различных начала урл.
ДЛя начала надо узнать какой именно из них, что бы потом его отрезать.
Что то у меня такое условие только начало с майл отрезает, а остальные оставляет как были.

Code: [Select]

for($var, $var < 4)
 $varm = $var + 1
 $_ankf = TFRead("name.txt", $varm)
 
 IF STRPOS ($_ankf, "mail/") = 1   
$pos =  STRPOS($_ankf, "mail/") + 5
 END_IF
 
  IF  STRPOS($_ankf, "inbox/") = 1   
$pos =  STRPOS($_ankf, "inbox/") + 6
  END_IF
 
  IF  STRPOS($_ankf, "list/") = 1   
$pos =  STRPOS($_ankf, "list/") + 5
  END_IF
 
  IF  STRPOS($_ankf, "bk/") = 1   
$pos =  STRPOS($_ankf, "bk/") + 3
 END_IF

ps:
$_ankf = STRCUT2($_ankf, $pos, 100)

LOGWRITE ($_ankf)

END_CYC

« Last Edit: January 24, 2014, 07:34:47 PM by putman »

putman

  • Активный участник
  • ***
  • Posts: 199
    • View Profile
Re: Ускорение работы с файлом.
« Reply #7 on: January 24, 2014, 07:31:11 PM »
В коде выше у меня не работают условия, каждый раз входит во все IF.
Никак не могу найти как в условии проверять истинность присутствия одной из строк - list, inbox, mail или bk.
« Last Edit: January 24, 2014, 07:34:26 PM by putman »

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Re: Ускорение работы с файлом.
« Reply #8 on: January 24, 2014, 08:42:06 PM »
Вот правильный код
Code: (clickermann) [Select]
for($var, $var < 4)
   $pos = 0
   $_ankf = TFRead("name.txt", $var+1)
   
   IF((STRPOS ($_ankf, "mail/") > 0) & ($pos = 0))
      $pos =  STRPOS($_ankf, "mail/") + 5
   END_IF
   
   IF((STRPOS($_ankf, "inbox/") > 0) & ($pos = 0))
      $pos =  STRPOS($_ankf, "inbox/") + 6
   END_IF
   
   IF((STRPOS($_ankf, "list/") > 0) & ($pos = 0))
      $pos =  STRPOS($_ankf, "list/") + 5
   END_IF
   
   IF((STRPOS($_ankf, "bk/") > 0) & ($pos = 0))
      $pos =  STRPOS($_ankf, "bk/") + 3
   END_IF

   $_ankf = STRCUT2($_ankf, $pos, 100)
   
   LOGWRITE ($_ankf)
   
END_CYC
« Last Edit: January 24, 2014, 08:45:10 PM by Oraven »

putman

  • Активный участник
  • ***
  • Posts: 199
    • View Profile
Re: Ускорение работы с файлом.
« Reply #9 on: January 24, 2014, 10:41:39 PM »
Вот правильный код
...
Этот код отрезает одинаковое количество символов, то которое указано в первом условии, в данном случае это + 3.
На остальные условия (с разными длинами доменов) он не реагирует, какие бы цифры там не стояли.
Code: [Select]
   IF((STRPOS ($_ankf, "mail/") > 0) & ($pos = 0))
     $pos =  STRPOS($_ankf, "mail/") + 3
  END_IF
т.е. получается
Code: [Select]
23:37:13 l/goldsmetana/
23:37:13 xxx1910xxx19010/
23:37:13 ox/lagonet/
23:37:13 t/bagira19/

Oraven

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3685
  • Котэ
    • View Profile
Re: Ускорение работы с файлом.
« Reply #10 on: January 25, 2014, 01:42:59 AM »
Сделал файл "name.txt". Записал туда такие строки
Code: [Select]
http://my.mail.ru/mail/goldsmetana/
http://my.mail.ru/bk/xxx1910xxx19010/
http://my.mail.ru/list/lagonet/
http://my.mail.ru/inbox/bagira19/

Поместил рядом скрипт, запустил и в логе получил:
Code: [Select]
2:40:39 goldsmetana/
2:40:39 xxx1910xxx19010/
2:40:39 lagonet/
2:40:39 bagira19/

Что у тебя не так?

putman

  • Активный участник
  • ***
  • Posts: 199
    • View Profile
Re: Ускорение работы с файлом.
« Reply #11 on: January 26, 2014, 06:26:38 PM »
Большое спасибо !
Ваш код работает, не знаю, что я не так скопировал в первый раз. Скопировал снова, вставил, работает.

Vint

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: Ускорение работы с файлом.
« Reply #12 on: January 28, 2014, 02:58:22 PM »
Самому стало интересно. Сделал ряд опытов. Забыл выложить, исправляюсь.

Создал генератором 2 файла в одном полные адреса, во втором только значимая часть.

Первые два теста не работа с файлом, а вырезание короткой части.
Тест 1 - вариант Андрея
Тест 2 -  вложенными условиями
Искать буду существующий адрес (для контроля) записанный последним для равного числа переборов.
Тестовый файл взял на 1000 адресов.
Результаты привожу для компа с работы, довольно тормознутого. Чем быстрее комп тем меньше разница в результатах.

результат 47 и 22 мс соответственно
В принципе эта часть вызывается всего 1 раз при каждом поиске, поэтому сильно не влияет. Но всё-таки.


Тест 3 - прямым перебором строк напрямую сравниваем длинные адреса с длинным образцом
Тест 4 - то же, для коротких адресов
Тест 5 - не удался из-за ограничения длины переменной в 4.8, пришлось пропустить
Тест 6 - короткие адреса, через массив. Считываем файл 1 раз, далее работаем с массивом параллельно дописывая в файл новые данные.
Тест 7 - сделал поиск в файле в AutoIt, параметры передавал/принимал через ini. Учтено время, в т.ч на вызов exe.


Результаты:

13:59:27 Время теста
13:59:27 Тест 1   47 мс
13:59:27 Тест 2   22 мс
13:59:27 
13:59:27 Тест 3.   Длинные 1337 мс
13:59:27 Тест 4.   Короткие 1108 мс
13:59:27 Тест 6.   Короткие в массив 522 мс
13:59:27 Тест 7.   Короткие. Вызов AutoIt 111 мс

Выводы:
короткие адреса дают выигрыш против длинных -17%, смысл есть.
массивы против прямого перебора из файла дают выигрыш -52%, смысл есть.Не знаю, почему у тебя получилось одинаково.
через вызов сторонней скомпилированной программы (знал бы С++ сделал бы на нём) против массивов -78%, против коротких прямых -90%

Если нигде не накосячил...
Все файлы во вложении.
Само собой от запуска к запуску результаты чуть разнятся.

Массивы это хорошо. В чистом кликере нужно через них.
Автоит не рекламирую. Кстати в обычном, не скомпилированном скрипте результаты точь в точь совпадают с результатами на массивах в кликере. Это толстый намёк на необходимую не только для закрытости компиляцию...  :)

Можно ещё ускорить, разделив хранящиеся данные по 4 файлам в зависимости от домена. mail, bk, inbox, list. И искать каждый только в своём домене.
Предполагаю, что в домене mail адресов гораздо больше, чем в других. Нужно сделать анализ, подсчитать реальные адреса. И если mail = bk+inbox+list можно делить на 2 файла.
Если конечно предполагается большая база, то лучше на 4. Я бы выжимал скорость сразу всеми способами, даже дающими незначительное ускорение.

Code: (clickermann) [Select]
#name "Работа с файлом"
// Author: Vint
// Version: 1.1 (28.01.2014)
// Для 4.9 (003)


//==============================================================================
SUB (itog)    //  вывод затраченного времени
   $test_time = $_ms-$start
   LOGWRITE ("Время теста. Вариант ", $v1, "   ", $test_time, " мс")
   LOGWRITE (" ")
   LOGWRITE ("-------------------------------------------------")
END_SUB

//==============================================================================

LOGCLEAR


// тест 1 вариант 1  длинный адрес
$start = $_ms
$v1 = 1
for($var, $var < 10)
   $pos = 0
   $_ankf = TFRead("name.txt", $var+1)
   
   IF((STRPOS ($_ankf, "mail/") > 0) & ($pos = 0))
      $pos =  STRPOS($_ankf, "mail/") + 5
   END_IF
   
   IF((STRPOS($_ankf, "inbox/") > 0) & ($pos = 0))
      $pos =  STRPOS($_ankf, "inbox/") + 6
   END_IF
   
   IF((STRPOS($_ankf, "list/") > 0) & ($pos = 0))
      $pos =  STRPOS($_ankf, "list/") + 5
   END_IF
   
   IF((STRPOS($_ankf, "bk/") > 0) & ($pos = 0))
      $pos =  STRPOS($_ankf, "bk/") + 3
   END_IF
   
   $_ankf = STRCUT2($_ankf, $pos, 100)
   //LOGWRITE ($_ankf)
END_CYC
itog()
$test_time1 = $test_time


// тест 2 вариант 2  короткий адрес
UNDEFINE($url)
$start = $_ms
$v1 = 2
for($var, $var < 10)
   $url = TFRead("name.txt", $var+1)
   IF(STRPOS ($url, "mail/") > 0)
      $url = STRCUT2($url, STRPOS($url, "mail/")+5, 100)
   ELSE
      IF(STRPOS ($url, "inbox/") > 0)
         $url = STRCUT2($url, STRPOS($url, "inbox/")+6, 100)
      ELSE
         IF(STRPOS ($url, "list/") > 0)
            $url = STRCUT2($url, STRPOS($url, "list/")+5, 100)
         ELSE
            IF(STRPOS ($url, "bk/") > 0)
               $url = STRCUT2($url, STRPOS($url, "bk/")+3, 100)
            END_IF
         END_IF
      END_IF
   END_IF
   $url = STRCUT2($url, 1, STRPOS($url, "/")-1)
   
   //LOGWRITE ($url)
END_CYC
itog()
$test_time2 = $test_time


// тест 3  прямое сравнение длинных
UNDEFINE($url)
$ank = "http://my.mail.ru/mail/aicauro/"
$start = $_ms
$v1 = 3
for ($i, $i<TFCOUNT("name.txt"))
   $url = TFRead("name.txt", $i+1)
   IF($ank = $url)
      LOGWRITE ("Имя есть в базе")
   END_IF
end_cyc
itog()
$test_time3 = $test_time


// тест 4   прямое сравнение коротких
UNDEFINE($url)
$ank = "aicauro"
$start = $_ms
$v1 = 4
for ($i, $i<TFCOUNT("name_small.txt"))
   $url = TFRead("name_small.txt", $i+1)
   IF($ank = $url)
      LOGWRITE ("Имя есть в базе")
   END_IF
end_cyc
itog()
$test_time4 = $test_time


// тест 5   короткие в строку
//UNDEFINE($url)
//$ank = "aicauro"
//$url = ""
//$v1 = 5
//for ($i, $i<TFCOUNT("name_small.txt"))
//   $url = STRCONCAT($url, TFRead("name_small.txt", $i))
//end_cyc
//LOGWRITE ("$url = ", $url)
//LOGWRITE ("Len ", STRLEN($url))



//$start = $_ms
//IF(STRPOS($url, $ank) > 0)
//   LOGWRITE ("Имя есть в базе")
//ELSE
//   //LOGWRITE ("Имени нет в базе")
//END_IF
//$url = STRCONCAT($url, $ank)
//GOSUB(itog)
//$test_time5 = $test_time


// тест 6   короткие в массив
UNDEFINE($url)
$ank = "aicauro"
$url = ""
$v1 = 6
for ($i, $i<TFCOUNT("name_small.txt"))
   $data = TFRead("name_small.txt", $i+1)
   ARRPUSH($url, $data)
end_cyc
//LOGWRITE ("ARRSIZE = ", ARRSIZE($url2))

$start = $_ms
for ($i, $i < ARRSIZE($url))
   IF($ank = $url[$i])
      LOGWRITE ("Имя есть в базе")
   END_IF
end_cyc
$url = ARRPUSH($url, $ank)
itog()
$test_time6 = $test_time


// тест 7   вызов AutoIt
UNDEFINE($url)
$ank = "aicauro"
$url = ""
$v1 = 7
INIWRITE("name.ini","file","name_small.txt")
$start = $_ms
INIWRITE("name.ini","ank",$ank)
INIWRITE("name.ini","return","-1")
EXECUTE("Find file.exe")
WHILE(INT(INIREAD("name.ini", "return")) = -1) // ожидание
   WAITMS(30)
   //LOGWRITE ("Ждём")
END_CYC
IF(INT(INIREAD("name.ini", "return")) = 1)
   LOGWRITE ("Имя есть в базе")
END_IF
itog()
$test_time7 = $test_time

WAIT(1)
LOGWRITE (" ")
LOGWRITE ("Время теста")
LOGWRITE ("Тест 1 ", $test_time1, " мс")
LOGWRITE ("Тест 2 ", $test_time2, " мс")
LOGWRITE (" ")
LOGWRITE ("Тест 3. Длинные ", $test_time3, " мс")
LOGWRITE ("Тест 4. Короткие ", $test_time4, " мс")
//LOGWRITE ("Тест 5. Короткие в строку ", $test_time5, " мс")
LOGWRITE ("Тест 6. Короткие в массив ", $test_time6, " мс")
LOGWRITE ("Тест 7. Короткие. Вызов AutoIt ", $test_time7, " мс")
HALT
« Last Edit: January 28, 2014, 03:07:54 PM by Vint »


putman

  • Активный участник
  • ***
  • Posts: 199
    • View Profile
Re: Ускорение работы с файлом.
« Reply #13 on: January 28, 2014, 07:57:36 PM »
Vint, спасибо, буду изучать код.
Сравнение сторонней быстрой программой очень интересно.
Еще я хотел в каждый элемент массива писать не одно значение, а например 20, длиной по 12 символов допустим, мне кажется будет быстрее, надо проверить.

putman

  • Активный участник
  • ***
  • Posts: 199
    • View Profile
Re: Ускорение работы с файлом.
« Reply #14 on: January 28, 2014, 08:04:34 PM »
C find file отлично получается, подскажите, где почитать про работу с внешними программами поиска.
А то, ничего не понял в той части программы, где эта работа реализована.
У меня получилось:

Quote
21:05:23 Время теста
21:05:23 Тест 1 32 мс
21:05:23 Тест 2 15 мс
21:05:23 
21:05:23 Тест 3. Длинные 1270 мс
21:05:23 Тест 4. Короткие 1227 мс
21:05:23 Тест 6. Короткие в массив 874 мс
21:05:23 Тест 7. Короткие. Вызов AutoIt 50 мс

, вот повторный тест.

Quote
21:08:07 Время теста
21:08:07 Тест 1 55 мс
21:08:07 Тест 2 12 мс
21:08:07 
21:08:07 Тест 3. Длинные 850 мс
21:08:07 Тест 4. Короткие 772 мс
21:08:07 Тест 6. Короткие в массив 444 мс
21:08:07 Тест 7. Короткие. Вызов AutoIt 55 мс

Почему такой большой разброс интересно ?
« Last Edit: January 28, 2014, 08:09:09 PM by putman »