Mercurial > vim
comparison src/search.c @ 29071:b90bca860b5a v8.2.5057
patch 8.2.5057: using gettimeofday() for timeout is very inefficient
Commit: https://github.com/vim/vim/commit/6574577cacd393ab7591fc776ea060eebc939e55
Author: Paul Ollis <paul@cleversheep.org>
Date: Sun Jun 5 16:55:54 2022 +0100
patch 8.2.5057: using gettimeofday() for timeout is very inefficient
Problem: Using gettimeofday() for timeout is very inefficient.
Solution: Set a platform dependent timer. (Paul Ollis, closes https://github.com/vim/vim/issues/10505)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 05 Jun 2022 18:00:08 +0200 |
parents | 485619e7f836 |
children | d1e263ecf634 |
comparison
equal
deleted
inserted
replaced
29070:8bf8001ef6d5 | 29071:b90bca860b5a |
---|---|
656 int called_emsg_before = called_emsg; | 656 int called_emsg_before = called_emsg; |
657 #ifdef FEAT_SEARCH_EXTRA | 657 #ifdef FEAT_SEARCH_EXTRA |
658 int break_loop = FALSE; | 658 int break_loop = FALSE; |
659 #endif | 659 #endif |
660 linenr_T stop_lnum = 0; // stop after this line number when != 0 | 660 linenr_T stop_lnum = 0; // stop after this line number when != 0 |
661 #ifdef FEAT_RELTIME | 661 int unused_timeout_flag = FALSE; |
662 proftime_T *tm = NULL; // timeout limit or NULL | 662 int *timed_out = &unused_timeout_flag; // set when timed out. |
663 int *timed_out = NULL; // set when timed out or NULL | |
664 #endif | |
665 | |
666 if (extra_arg != NULL) | |
667 { | |
668 stop_lnum = extra_arg->sa_stop_lnum; | |
669 #ifdef FEAT_RELTIME | |
670 tm = extra_arg->sa_tm; | |
671 timed_out = &extra_arg->sa_timed_out; | |
672 #endif | |
673 } | |
674 | 663 |
675 if (search_regcomp(pat, RE_SEARCH, pat_use, | 664 if (search_regcomp(pat, RE_SEARCH, pat_use, |
676 (options & (SEARCH_HIS + SEARCH_KEEP)), ®match) == FAIL) | 665 (options & (SEARCH_HIS + SEARCH_KEEP)), ®match) == FAIL) |
677 { | 666 { |
678 if ((options & SEARCH_MSG) && !rc_did_emsg) | 667 if ((options & SEARCH_MSG) && !rc_did_emsg) |
679 semsg(_(e_invalid_search_string_str), mr_pattern); | 668 semsg(_(e_invalid_search_string_str), mr_pattern); |
680 return FAIL; | 669 return FAIL; |
670 } | |
671 | |
672 if (extra_arg != NULL) | |
673 { | |
674 stop_lnum = extra_arg->sa_stop_lnum; | |
675 #ifdef FEAT_RELTIME | |
676 if (extra_arg->sa_tm > 0) | |
677 { | |
678 init_regexp_timeout(extra_arg->sa_tm); | |
679 timed_out = &extra_arg->sa_timed_out; | |
680 } | |
681 #endif | |
681 } | 682 } |
682 | 683 |
683 /* | 684 /* |
684 * find the string | 685 * find the string |
685 */ | 686 */ |
751 { | 752 { |
752 // Stop after checking "stop_lnum", if it's set. | 753 // Stop after checking "stop_lnum", if it's set. |
753 if (stop_lnum != 0 && (dir == FORWARD | 754 if (stop_lnum != 0 && (dir == FORWARD |
754 ? lnum > stop_lnum : lnum < stop_lnum)) | 755 ? lnum > stop_lnum : lnum < stop_lnum)) |
755 break; | 756 break; |
756 #ifdef FEAT_RELTIME | 757 // Stop after passing the time limit. |
757 // Stop after passing the "tm" time limit. | 758 if (*timed_out) |
758 if (tm != NULL && profile_passed_limit(tm)) | |
759 break; | 759 break; |
760 #endif | |
761 | 760 |
762 /* | 761 /* |
763 * Look for a match somewhere in line "lnum". | 762 * Look for a match somewhere in line "lnum". |
764 */ | 763 */ |
765 col = at_first_line && (options & SEARCH_COL) ? pos->col | 764 col = at_first_line && (options & SEARCH_COL) ? pos->col |
766 : (colnr_T)0; | 765 : (colnr_T)0; |
767 nmatched = vim_regexec_multi(®match, win, buf, | 766 nmatched = vim_regexec_multi(®match, win, buf, |
768 lnum, col, | 767 lnum, col, timed_out); |
769 #ifdef FEAT_RELTIME | |
770 tm, timed_out | |
771 #else | |
772 NULL, NULL | |
773 #endif | |
774 ); | |
775 // vim_regexec_multi() may clear "regprog" | 768 // vim_regexec_multi() may clear "regprog" |
776 if (regmatch.regprog == NULL) | 769 if (regmatch.regprog == NULL) |
777 break; | 770 break; |
778 // Abort searching on an error (e.g., out of stack). | 771 // Abort searching on an error (e.g., out of stack). |
779 if (called_emsg > called_emsg_before | 772 if (called_emsg > called_emsg_before || *timed_out) |
780 #ifdef FEAT_RELTIME | |
781 || (timed_out != NULL && *timed_out) | |
782 #endif | |
783 ) | |
784 break; | 773 break; |
785 if (nmatched > 0) | 774 if (nmatched > 0) |
786 { | 775 { |
787 // match may actually be in another line when using \zs | 776 // match may actually be in another line when using \zs |
788 matchpos = regmatch.startpos[0]; | 777 matchpos = regmatch.startpos[0]; |
861 if (matchcol == 0 && (options & SEARCH_START)) | 850 if (matchcol == 0 && (options & SEARCH_START)) |
862 break; | 851 break; |
863 if (ptr[matchcol] == NUL | 852 if (ptr[matchcol] == NUL |
864 || (nmatched = vim_regexec_multi(®match, | 853 || (nmatched = vim_regexec_multi(®match, |
865 win, buf, lnum + matchpos.lnum, | 854 win, buf, lnum + matchpos.lnum, |
866 matchcol, | 855 matchcol, timed_out)) == 0) |
867 #ifdef FEAT_RELTIME | |
868 tm, timed_out | |
869 #else | |
870 NULL, NULL | |
871 #endif | |
872 )) == 0) | |
873 { | 856 { |
874 match_ok = FALSE; | 857 match_ok = FALSE; |
875 break; | 858 break; |
876 } | 859 } |
877 // vim_regexec_multi() may clear "regprog" | 860 // vim_regexec_multi() may clear "regprog" |
972 } | 955 } |
973 } | 956 } |
974 if (ptr[matchcol] == NUL | 957 if (ptr[matchcol] == NUL |
975 || (nmatched = vim_regexec_multi(®match, | 958 || (nmatched = vim_regexec_multi(®match, |
976 win, buf, lnum + matchpos.lnum, | 959 win, buf, lnum + matchpos.lnum, |
977 matchcol, | 960 matchcol, timed_out)) == 0) |
978 #ifdef FEAT_RELTIME | |
979 tm, timed_out | |
980 #else | |
981 NULL, NULL | |
982 #endif | |
983 )) == 0) | |
984 { | 961 { |
985 #ifdef FEAT_RELTIME | |
986 // If the search timed out, we did find a match | 962 // If the search timed out, we did find a match |
987 // but it might be the wrong one, so that's not | 963 // but it might be the wrong one, so that's not |
988 // OK. | 964 // OK. |
989 if (timed_out != NULL && *timed_out) | 965 if (*timed_out) |
990 match_ok = FALSE; | 966 match_ok = FALSE; |
991 #endif | |
992 break; | 967 break; |
993 } | 968 } |
994 // vim_regexec_multi() may clear "regprog" | 969 // vim_regexec_multi() may clear "regprog" |
995 if (regmatch.regprog == NULL) | 970 if (regmatch.regprog == NULL) |
996 break; | 971 break; |
1095 * Stop the search if wrapscan isn't set, "stop_lnum" is | 1070 * Stop the search if wrapscan isn't set, "stop_lnum" is |
1096 * specified, after an interrupt, after a match and after looping | 1071 * specified, after an interrupt, after a match and after looping |
1097 * twice. | 1072 * twice. |
1098 */ | 1073 */ |
1099 if (!p_ws || stop_lnum != 0 || got_int | 1074 if (!p_ws || stop_lnum != 0 || got_int |
1100 || called_emsg > called_emsg_before | 1075 || called_emsg > called_emsg_before || *timed_out |
1101 #ifdef FEAT_RELTIME | |
1102 || (timed_out != NULL && *timed_out) | |
1103 #endif | |
1104 #ifdef FEAT_SEARCH_EXTRA | 1076 #ifdef FEAT_SEARCH_EXTRA |
1105 || break_loop | 1077 || break_loop |
1106 #endif | 1078 #endif |
1107 || found || loop) | 1079 || found || loop) |
1108 break; | 1080 break; |
1122 give_warning((char_u *)_(dir == BACKWARD | 1094 give_warning((char_u *)_(dir == BACKWARD |
1123 ? top_bot_msg : bot_top_msg), TRUE); | 1095 ? top_bot_msg : bot_top_msg), TRUE); |
1124 if (extra_arg != NULL) | 1096 if (extra_arg != NULL) |
1125 extra_arg->sa_wrapped = TRUE; | 1097 extra_arg->sa_wrapped = TRUE; |
1126 } | 1098 } |
1127 if (got_int || called_emsg > called_emsg_before | 1099 if (got_int || called_emsg > called_emsg_before || *timed_out |
1128 #ifdef FEAT_RELTIME | |
1129 || (timed_out != NULL && *timed_out) | |
1130 #endif | |
1131 #ifdef FEAT_SEARCH_EXTRA | 1100 #ifdef FEAT_SEARCH_EXTRA |
1132 || break_loop | 1101 || break_loop |
1133 #endif | 1102 #endif |
1134 ) | 1103 ) |
1135 break; | 1104 break; |
1136 } | 1105 } |
1137 while (--count > 0 && found); // stop after count matches or no match | 1106 while (--count > 0 && found); // stop after count matches or no match |
1138 | 1107 |
1108 # ifdef FEAT_RELTIME | |
1109 disable_regexp_timeout(); | |
1110 # endif | |
1139 vim_regfree(regmatch.regprog); | 1111 vim_regfree(regmatch.regprog); |
1140 | 1112 |
1141 if (!found) // did not find it | 1113 if (!found) // did not find it |
1142 { | 1114 { |
1143 if (got_int) | 1115 if (got_int) |
2913 // start and end are in the same position. | 2885 // start and end are in the same position. |
2914 do | 2886 do |
2915 { | 2887 { |
2916 regmatch.startpos[0].col++; | 2888 regmatch.startpos[0].col++; |
2917 nmatched = vim_regexec_multi(®match, curwin, curbuf, | 2889 nmatched = vim_regexec_multi(®match, curwin, curbuf, |
2918 pos.lnum, regmatch.startpos[0].col, NULL, NULL); | 2890 pos.lnum, regmatch.startpos[0].col, NULL); |
2919 if (nmatched != 0) | 2891 if (nmatched != 0) |
2920 break; | 2892 break; |
2921 } while (regmatch.regprog != NULL | 2893 } while (regmatch.regprog != NULL |
2922 && direction == FORWARD ? regmatch.startpos[0].col < pos.col | 2894 && direction == FORWARD ? regmatch.startpos[0].col < pos.col |
2923 : regmatch.startpos[0].col > pos.col); | 2895 : regmatch.startpos[0].col > pos.col); |