![]() |
|
Модераторы: 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. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |