comparison src/buffer.c @ 15247:336728a577f5 v8.1.0632

patch 8.1.0632: using sign group names is inefficient commit https://github.com/vim/vim/commit/7a2d9892b7158edf8dc48e9bcaaae70a40787b37 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Dec 24 20:23:49 2018 +0100 patch 8.1.0632: using sign group names is inefficient Problem: Using sign group names is inefficient. Solution: Store group names in a hash table and use a reference to them. Also remove unnecessary use of ":exe" from the tests. (Yegappan Lakshmanan, closes #3715)
author Bram Moolenaar <Bram@vim.org>
date Mon, 24 Dec 2018 20:30:04 +0100
parents 3a99b2e6d136
children a6319aca721b
comparison
equal deleted inserted replaced
15246:a6fc4675cf61 15247:336728a577f5
5863 return OK; 5863 return OK;
5864 } 5864 }
5865 #endif 5865 #endif
5866 5866
5867 #if defined(FEAT_SIGNS) || defined(PROTO) 5867 #if defined(FEAT_SIGNS) || defined(PROTO)
5868 static hashtab_T sg_table; // sign group (signgroup_T) hashtable
5869
5870 /*
5871 * A new sign in group 'groupname' is added. If the group is not present,
5872 * create it. Otherwise reference the group.
5873 */
5874 static signgroup_T *
5875 sign_group_ref(char_u *groupname)
5876 {
5877 static int initialized = FALSE;
5878 hash_T hash;
5879 hashitem_T *hi;
5880 signgroup_T *group;
5881
5882 if (!initialized)
5883 {
5884 initialized = TRUE;
5885 hash_init(&sg_table);
5886 }
5887
5888 hash = hash_hash(groupname);
5889 hi = hash_lookup(&sg_table, groupname, hash);
5890 if (HASHITEM_EMPTY(hi))
5891 {
5892 // new group
5893 group = (signgroup_T *)alloc(
5894 (unsigned)(sizeof(signgroup_T) + STRLEN(groupname)));
5895 if (group == NULL)
5896 return NULL;
5897 STRCPY(group->sg_name, groupname);
5898 group->refcount = 1;
5899 hash_add_item(&sg_table, hi, group->sg_name, hash);
5900 }
5901 else
5902 {
5903 // existing group
5904 group = HI2SG(hi);
5905 group->refcount++;
5906 }
5907
5908 return group;
5909 }
5910
5911 /*
5912 * A sign in group 'groupname' is removed. If all the signs in this group are
5913 * removed, then remove the group.
5914 */
5915 static void
5916 sign_group_unref(char_u *groupname)
5917 {
5918 hashitem_T *hi;
5919 signgroup_T *group;
5920
5921 hi = hash_find(&sg_table, groupname);
5922 if (!HASHITEM_EMPTY(hi))
5923 {
5924 group = HI2SG(hi);
5925 group->refcount--;
5926 if (group->refcount == 0)
5927 {
5928 // All the signs in this group are removed
5929 hash_remove(&sg_table, hi);
5930 vim_free(group);
5931 }
5932 }
5933 }
5934
5868 /* 5935 /*
5869 * Insert a new sign into the signlist for buffer 'buf' between the 'prev' and 5936 * Insert a new sign into the signlist for buffer 'buf' between the 'prev' and
5870 * 'next' signs. 5937 * 'next' signs.
5871 */ 5938 */
5872 static void 5939 static void
5888 { 5955 {
5889 newsign->id = id; 5956 newsign->id = id;
5890 newsign->lnum = lnum; 5957 newsign->lnum = lnum;
5891 newsign->typenr = typenr; 5958 newsign->typenr = typenr;
5892 if (group != NULL) 5959 if (group != NULL)
5893 newsign->group = vim_strsave(group); 5960 {
5961 newsign->group = sign_group_ref(group);
5962 if (newsign->group == NULL)
5963 {
5964 vim_free(newsign);
5965 return;
5966 }
5967 }
5894 else 5968 else
5895 newsign->group = NULL; 5969 newsign->group = NULL;
5896 newsign->priority = prio; 5970 newsign->priority = prio;
5897 newsign->next = next; 5971 newsign->next = next;
5898 newsign->prev = prev; 5972 newsign->prev = prev;
5957 sign_in_group(signlist_T *sign, char_u *group) 6031 sign_in_group(signlist_T *sign, char_u *group)
5958 { 6032 {
5959 return ((group != NULL && STRCMP(group, "*") == 0) || 6033 return ((group != NULL && STRCMP(group, "*") == 0) ||
5960 (group == NULL && sign->group == NULL) || 6034 (group == NULL && sign->group == NULL) ||
5961 (group != NULL && sign->group != NULL && 6035 (group != NULL && sign->group != NULL &&
5962 STRCMP(group, sign->group) == 0)); 6036 STRCMP(group, sign->group->sg_name) == 0));
5963 } 6037 }
5964 6038
5965 /* 6039 /*
5966 * Return information about a sign in a Dict 6040 * Return information about a sign in a Dict
5967 */ 6041 */
5972 6046
5973 if ((d = dict_alloc_id(aid_sign_getinfo)) == NULL) 6047 if ((d = dict_alloc_id(aid_sign_getinfo)) == NULL)
5974 return NULL; 6048 return NULL;
5975 dict_add_number(d, "id", sign->id); 6049 dict_add_number(d, "id", sign->id);
5976 dict_add_string(d, "group", (sign->group == NULL) ? 6050 dict_add_string(d, "group", (sign->group == NULL) ?
5977 (char_u *)"" : sign->group); 6051 (char_u *)"" : sign->group->sg_name);
5978 dict_add_number(d, "lnum", sign->lnum); 6052 dict_add_number(d, "lnum", sign->lnum);
5979 dict_add_string(d, "name", sign_typenr2name(sign->typenr)); 6053 dict_add_string(d, "name", sign_typenr2name(sign->typenr));
5980 dict_add_number(d, "priority", sign->priority); 6054 dict_add_number(d, "priority", sign->priority);
5981 6055
5982 return d; 6056 return d;
5987 */ 6061 */
5988 void 6062 void
5989 buf_addsign( 6063 buf_addsign(
5990 buf_T *buf, // buffer to store sign in 6064 buf_T *buf, // buffer to store sign in
5991 int id, // sign ID 6065 int id, // sign ID
5992 char_u *group, // sign group 6066 char_u *groupname, // sign group
5993 int prio, // sign priority 6067 int prio, // sign priority
5994 linenr_T lnum, // line number which gets the mark 6068 linenr_T lnum, // line number which gets the mark
5995 int typenr) // typenr of sign we are adding 6069 int typenr) // typenr of sign we are adding
5996 { 6070 {
5997 signlist_T *sign; // a sign in the signlist 6071 signlist_T *sign; // a sign in the signlist
5999 6073
6000 prev = NULL; 6074 prev = NULL;
6001 FOR_ALL_SIGNS_IN_BUF(buf) 6075 FOR_ALL_SIGNS_IN_BUF(buf)
6002 { 6076 {
6003 if (lnum == sign->lnum && id == sign->id && 6077 if (lnum == sign->lnum && id == sign->id &&
6004 sign_in_group(sign, group)) 6078 sign_in_group(sign, groupname))
6005 { 6079 {
6006 // Update an existing sign 6080 // Update an existing sign
6007 sign->typenr = typenr; 6081 sign->typenr = typenr;
6008 return; 6082 return;
6009 } 6083 }
6010 else if (lnum < sign->lnum) 6084 else if (lnum < sign->lnum)
6011 { 6085 {
6012 insert_sign_by_lnum_prio(buf, prev, id, group, prio, lnum, typenr); 6086 insert_sign_by_lnum_prio(buf, prev, id, groupname, prio,
6087 lnum, typenr);
6013 return; 6088 return;
6014 } 6089 }
6015 prev = sign; 6090 prev = sign;
6016 } 6091 }
6017 6092
6018 insert_sign_by_lnum_prio(buf, prev, id, group, prio, lnum, typenr); 6093 insert_sign_by_lnum_prio(buf, prev, id, groupname, prio, lnum, typenr);
6019
6020 return; 6094 return;
6021 } 6095 }
6022 6096
6023 /* 6097 /*
6024 * For an existing, placed sign "markId" change the type to "typenr". 6098 * For an existing, placed sign "markId" change the type to "typenr".
6104 { 6178 {
6105 *lastp = next; 6179 *lastp = next;
6106 if (next != NULL) 6180 if (next != NULL)
6107 next->prev = sign->prev; 6181 next->prev = sign->prev;
6108 lnum = sign->lnum; 6182 lnum = sign->lnum;
6109 vim_free(sign->group); 6183 if (sign->group != NULL)
6184 sign_group_unref(sign->group->sg_name);
6110 vim_free(sign); 6185 vim_free(sign);
6111 // Check whether only one sign needs to be deleted 6186 // Check whether only one sign needs to be deleted
6112 if (group == NULL || (*group != '*' && id != 0)) 6187 if (group == NULL || (*group != '*' && id != 0))
6113 break; 6188 break;
6114 } 6189 }
6267 if (sign_in_group(sign, group)) 6342 if (sign_in_group(sign, group))
6268 { 6343 {
6269 *lastp = next; 6344 *lastp = next;
6270 if (next != NULL) 6345 if (next != NULL)
6271 next->prev = sign->prev; 6346 next->prev = sign->prev;
6272 vim_free(sign->group); 6347 if (sign->group != NULL)
6348 sign_group_unref(sign->group->sg_name);
6273 vim_free(sign); 6349 vim_free(sign);
6274 } 6350 }
6275 else 6351 else
6276 lastp = &sign->next; 6352 lastp = &sign->next;
6277 } 6353 }
6315 MSG_PUTS_ATTR(lbuf, HL_ATTR(HLF_D)); 6391 MSG_PUTS_ATTR(lbuf, HL_ATTR(HLF_D));
6316 msg_putchar('\n'); 6392 msg_putchar('\n');
6317 } 6393 }
6318 FOR_ALL_SIGNS_IN_BUF(buf) 6394 FOR_ALL_SIGNS_IN_BUF(buf)
6319 { 6395 {
6396 if (got_int)
6397 break;
6320 if (!sign_in_group(sign, sign_group)) 6398 if (!sign_in_group(sign, sign_group))
6321 continue; 6399 continue;
6322 if (sign->group != NULL) 6400 if (sign->group != NULL)
6323 vim_snprintf(group, BUFSIZ, " group=%s", sign->group); 6401 vim_snprintf(group, BUFSIZ, " group=%s",
6402 sign->group->sg_name);
6324 else 6403 else
6325 group[0] = '\0'; 6404 group[0] = '\0';
6326 vim_snprintf(lbuf, BUFSIZ, _(" line=%ld id=%d%s name=%s " 6405 vim_snprintf(lbuf, BUFSIZ, _(" line=%ld id=%d%s name=%s "
6327 "priority=%d"), 6406 "priority=%d"),
6328 (long)sign->lnum, sign->id, group, 6407 (long)sign->lnum, sign->id, group,