![]() |
Модераторы: bsa |
![]() ![]() ![]() |
|
SABROG |
|
||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 1 Всего: 91 |
Есть такой рабочий код:
Выглядит он, мягко говоря, кривовато. По сути это основной цикл StAX парсера. Проблема в следующем. С целью оптимизации создал 2 вложенных цикла. Раньше проверка isCritical() шла на каждом витке цикла. Профайлер четко мне сказал, что этот метод один из самых жрущих процессорное время. Метод atEnd() возвращает true в двух случаях: достиг конец документа (все ОК) и возникла ошибка. Ошибка может быть не критической, после которой возможно продолжение цикла, просто добавляется новая порция данных для парсинга. Т.е. теперь внутренний цикл выполняется без проверки на ошибку каждый раз. А если она возникает, то идет выход (atEnd) из внутреннего цикла во внешний. К сожалению в C++ нет метода типа ::break, чтобы выйти сразу из всех вложенных циклов. Пришлось вставить костыль в виде булевой переменной flag. По началу я впихнул проверку этой переменной наряду с isCritical таким образом:
Проблема возникла в особенности языка C++. Если первое условие не выполняется, то второе условие не проверяется вообще. Пришлось проверку вынести в if. Ума не приложу как в одну строчку написать такое условие: - если flag не установлен (false), то выходим из всех циклов, при условии, что isCritical() вернет положительное значение (true), при том, что если flag все-таки установлен (true), то выходим из циклов не зависимо от того, что вернет isCritical(). (flag==true && isCritical()==true||false) - выход из циклов (метод isCritical() должен вызываться только один раз) (flag==false && isCritical()==true) - выход из циклов (здесь метод isCritical() должен вызываться независимо от значения flag, т.к. происходящее внутри может на него повлиять при следующем витке, но как я говорил выше компилятор проверяет только первое условие, и если оно отрицательное, то второе условие не выполняется, что приводит к бесконечным итерациям.). Итого проблемы 2: - выход из двух вложенных циклов while без return или goto, отказавшись от проверки flag'a - или написать условие в одну строку, которое могло бы заставить компилятор проверять второе условие независимо от результатов проверки первого. |
||||
|
|||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 52 Всего: 211 |
остальное как-то запутанно написано, или мне сильно спать хочется. ![]() Это сообщение отредактировал(а) azesmcar - 30.7.2009, 21:39 |
|||
|
||||
GoldFinch |
|
|||
![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2141 Регистрация: 30.11.2008 Репутация: 6 Всего: 26 |
для выхода из 2х циклов сразу используйте return
|
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
если не сложно приведите первоначальный вариант парсера, мне кажется так будет легче помочь Вам правильно соптимизировать Ваш цикл.
|
|||
|
||||
ISergeyN |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 59 Регистрация: 11.10.2008 Где: Україна Репутация: 2 Всего: 2 |
||||
|
||||
SABROG |
|
||||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 1 Всего: 91 |
azesmcar, спасибо. Окончательный вариант получился таким:
Это мне тогда придется выносить цикл while в отдельный метод, т.к. после цикла идет еще код, а он не выполнится, если я выйду по return.
Первоначального не существует как такового, по крайней мере для Qt, где всё на словах в документации, а примеры довольно примитивные. Примеры на Java можно посмотреть тут http://www.cafeconleche.org/slides/sd2004west/stax/StAX.html , только вот они тоже очень уж примитивные. Как минимум там нет реализации того, что является главным достоинством StAX'a - поточности. А именно не реализован механизм догрузки данных с последующим продолжением парсинга. Именно на это нацелены эти 2 цикла. Когда данных не хватает (битый, частично загруженный xml) приходит ошибка. По сути ошибка не критичная и метод isCritical() проверяет характер ошибки и вызывает метод догрузки или ожидания новых данных. Если в процессе ожидания пользователь отменил дальнейший парсинг или пропала связь с сервером, то isCritical вернет true. Если новые данные были получены, то возвращается false и цикл продолжается дальше. Хотелось бы услышать еще мнения ЗА goto от других людей. |
||||
|
|||||
mes |
|
||||||||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
насколько понял Вам нужно прекратить цикл когда сработает одно из 3х условий:
ну так одна функция и не должна решать больше одной проблемы ![]() имелся ввиду парсер до начала Вашей оптимизации. ![]() отдайте предпочтение разбиению на функции - уверен, что не пожалеете. ![]() |
||||||||
|
|||||||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 52 Всего: 211 |
SABROG
По поводу goto http://forum.vingrad.ru/forum/topic-251118/0.html
Я бы перенес !flag на первое место, !isCritical() самая медленная проверка, пусть в первую очередь проверяется !flag, хотя это может избавить только от одного вызова IsCritical(), но все равно.. Мелочь а приятно ![]() Это сообщение отредактировал(а) azesmcar - 31.7.2009, 07:02 |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 1 Всего: 91 |
Да, я сам накосячил. Пробовал эти варианты, только у меня не было выхода по третьему условию (token != QXmlStreamReader::EndDocument). Весь мозг сломал почему не выходит из цикла
![]() Ты же вроде сам был против, поменял мнение? ![]() Пока сделал отдельный метод. Может его сделать inline, чтобы особо не влияло на скорость парсинга или компилер сам позаботится об этом ![]() |
|||
|
||||
azesmcar |
|
|||
![]() uploading... ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6291 Регистрация: 12.11.2004 Где: Армения Репутация: 52 Всего: 211 |
Где я это говорил? Я сказал Я лично никогда его не использовал, но там есть то что ты просил а именно, много мнений ![]() Добавлено через 1 минуту и 57 секунд
А сейчас медленно работает? Если нет - то зачем об этом думать? Скорость устраивает - все отлично, продолжай работать. Думать будешь об этом тогда, когда работать будет медленее чем ты от него ожидаешь. А так просто - оптимизация ради оптимизации зло. |
|||
|
||||
bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
Лично я считаю выход из вложенного цикла одним из случаев, когда использовать goto целесообразно. Так как введение дополнительного флага это уже пессимизация.
|
|||
|
||||
mes |
|
|||
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
ага, особенно если флаг притянут к логике цикла за уши. ![]() но все таки, учитывая предрасположения топик стартера (как мне они покзались, судя по этой теме) и мои опасения, что он может сделать не очень верные выводы добавлю: Не бойтесь разбивать на функции, и Вам будет удобнее, и компилятору и линкеру легче оптимизировать Ваш код - гораздо легче, чем если будете использовать гото. ![]() P.S. если в методе не используется this для успокоения души можете делать такой метод статическим. ![]() Это сообщение отредактировал(а) mes - 31.7.2009, 17:39 |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 1 Всего: 91 |
Вот эта фраза.
Ну да ладно, я в любом случае последовал совету mes'a. Оценил также совет bsa и сделал вывод, что в принципе в такой ситуации можно воспользоваться goto, но предпочту этого не делать, чтобы не вырабатывать в себе плохую привычку ;) Работать будет в любом случае медленно. На php парсинг того объема xml данных, что через меня проходит каждый день занимает минимум 30-40 минут в день (сам процесс парсинга). Обычно в сумме это где-то 300-400Мб. Когда я пытался в последний раз парсить это дело на C++ через DOM, то на это уходило минут 5. Не критично, но ведь не быстро. Думаю вопрос решен. |
|||
|
||||
![]() ![]() ![]() |
Правила форума "C/C++: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |