mirror of https://github.com/milvus-io/milvus.git
test: add test cases for mmap (#30942)
issue: https://github.com/milvus-io/milvus/issues/30940 Signed-off-by: elstic <hao.wang@zilliz.com>pull/31011/head
parent
71adafa933
commit
bd063a352d
|
@ -397,3 +397,19 @@ class ApiCollectionWrapper:
|
|||
res, check = api_request([self.collection.describe, timeout])
|
||||
check_result = ResponseChecker(res, func_name, check_task, check_items, check).run()
|
||||
return res, check_result
|
||||
|
||||
@trace()
|
||||
def alter_index(self, index_name, extra_params={}, timeout=None, check_task=None, check_items=None, **kwargs):
|
||||
timeout = TIMEOUT if timeout is None else timeout
|
||||
func_name = sys._getframe().f_code.co_name
|
||||
res, check = api_request([self.collection.alter_index, index_name, extra_params, timeout], **kwargs)
|
||||
check_result = ResponseChecker(res, func_name, check_task, check_items, check, **kwargs).run()
|
||||
return res, check_result
|
||||
|
||||
@trace()
|
||||
def set_properties(self, extra_params={}, timeout=None, check_task=None, check_items=None, **kwargs):
|
||||
timeout = TIMEOUT if timeout is None else timeout
|
||||
func_name = sys._getframe().f_code.co_name
|
||||
res, check = api_request([self.collection.set_properties, extra_params, timeout], **kwargs)
|
||||
check_result = ResponseChecker(res, func_name, check_task, check_items, check, **kwargs).run()
|
||||
return res, check_result
|
|
@ -12,7 +12,7 @@ allure-pytest==2.7.0
|
|||
pytest-print==0.2.1
|
||||
pytest-level==0.1.1
|
||||
pytest-xdist==2.5.0
|
||||
pymilvus==2.4.0rc33
|
||||
pymilvus==2.4.0rc36
|
||||
pytest-rerunfailures==9.1.1
|
||||
git+https://github.com/Projectplace/pytest-tags
|
||||
ndg-httpsclient
|
||||
|
|
|
@ -397,6 +397,29 @@ class TestAliasOperation(TestcaseBase):
|
|||
|
||||
assert res is True
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_enable_mmap_by_alias(self):
|
||||
"""
|
||||
target: enable or disable mmap by alias
|
||||
method: enable or disable mmap by alias
|
||||
expected: successfully enable mmap
|
||||
"""
|
||||
self._connect()
|
||||
c_name = cf.gen_unique_str("collection")
|
||||
collection_w, _ = self.collection_wrap.init_collection(c_name, schema=default_schema)
|
||||
alias_name = cf.gen_unique_str(prefix)
|
||||
self.utility_wrap.create_alias(collection_w.name, alias_name)
|
||||
collection_alias, _ = self.collection_wrap.init_collection(name=alias_name,
|
||||
check_task=CheckTasks.check_collection_property,
|
||||
check_items={exp_name: alias_name,
|
||||
exp_schema: default_schema})
|
||||
collection_alias.set_properties({'mmap.enabled': True})
|
||||
pro = collection_w.describe().get("properties")
|
||||
assert pro["mmap.enabled"] == 'True'
|
||||
collection_w.set_properties({'mmap.enabled': False})
|
||||
pro = collection_alias.describe().get("properties")
|
||||
assert pro["mmap.enabled"] == 'False'
|
||||
|
||||
|
||||
class TestAliasOperationInvalid(TestcaseBase):
|
||||
""" Negative test cases of alias interface operations"""
|
||||
|
|
|
@ -4512,3 +4512,132 @@ class TestCollectionMultipleVectorInvalid(TestcaseBase):
|
|||
error = {ct.err_code: 65535, ct.err_msg: "Invalid dim"}
|
||||
self.collection_wrap.init_collection(c_name, schema=schema, check_task=CheckTasks.err_res, check_items=error)
|
||||
|
||||
|
||||
class TestCollectionMmap(TestcaseBase):
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_describe_collection_mmap(self):
|
||||
"""
|
||||
target: enable or disable mmap in the collection
|
||||
method: enable or disable mmap in the collection
|
||||
expected: description information contains mmap
|
||||
"""
|
||||
self._connect()
|
||||
c_name = cf.gen_unique_str(prefix)
|
||||
collection_w, _ = self.collection_wrap.init_collection(c_name, schema=default_schema)
|
||||
collection_w.set_properties({'mmap.enabled': True})
|
||||
pro = collection_w.describe().get("properties")
|
||||
assert "mmap.enabled" in pro.keys()
|
||||
assert pro["mmap.enabled"] == 'True'
|
||||
collection_w.set_properties({'mmap.enabled': False})
|
||||
pro = collection_w.describe().get("properties")
|
||||
assert pro["mmap.enabled"] == 'False'
|
||||
collection_w.set_properties({'mmap.enabled': True})
|
||||
pro = collection_w.describe().get("properties")
|
||||
assert pro["mmap.enabled"] == 'True'
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
@pytest.mark.xfail(reason="issue: #30800")
|
||||
def test_load_mmap_collection(self):
|
||||
"""
|
||||
target: after loading, enable mmap for the collection
|
||||
method: 1. data preparation and create index
|
||||
2. load collection
|
||||
3. enable mmap on collection
|
||||
expected: raise exception
|
||||
"""
|
||||
self._connect()
|
||||
c_name = cf.gen_unique_str(prefix)
|
||||
collection_w, _ = self.collection_wrap.init_collection(c_name, schema=default_schema)
|
||||
collection_w.insert(cf.gen_default_list_data())
|
||||
collection_w.create_index(ct.default_float_vec_field_name, index_params=ct.default_flat_index,
|
||||
index_name=ct.default_index_name)
|
||||
collection_w.set_properties({'mmap.enabled': True})
|
||||
pro = collection_w.describe().get("properties")
|
||||
assert pro["mmap.enabled"] == 'True'
|
||||
collection_w.load()
|
||||
collection_w.set_properties({'mmap.enabled': True},
|
||||
check_items={ct.err_code: 104,
|
||||
ct.err_msg: f"collection already loaded"})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_drop_mmap_collection(self):
|
||||
"""
|
||||
target: set mmap on collection
|
||||
method: 1. set mmap on collection
|
||||
2. drop collection
|
||||
3. describe collection
|
||||
expected: description information contains mmap
|
||||
"""
|
||||
self._connect()
|
||||
c_name = "coll_rand"
|
||||
collection_w, _ = self.collection_wrap.init_collection(c_name, schema=default_schema)
|
||||
collection_w.set_properties({'mmap.enabled': True})
|
||||
collection_w.drop()
|
||||
collection_w, _ = self.collection_wrap.init_collection(c_name, schema=default_schema)
|
||||
pro = collection_w.describe().get("properties")
|
||||
assert "mmap.enabled" not in pro.keys()
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_multiple_collections_enable_mmap(self):
|
||||
"""
|
||||
target: enabling mmap for multiple collections in a single instance
|
||||
method: enabling mmap for multiple collections in a single instance
|
||||
expected: the collection description message for mmap is normal
|
||||
"""
|
||||
self._connect()
|
||||
c_name = "coll_1"
|
||||
c_name2 = "coll_2"
|
||||
c_name3 = "coll_3"
|
||||
collection_w, _ = self.collection_wrap.init_collection(c_name, schema=default_schema)
|
||||
collection_w2, _ = self.collection_wrap.init_collection(c_name2, schema=default_schema)
|
||||
collection_w3, _ = self.collection_wrap.init_collection(c_name3, schema=default_schema)
|
||||
collection_w.set_properties({'mmap.enabled': True})
|
||||
collection_w2.set_properties({'mmap.enabled': True})
|
||||
pro = collection_w.describe().get("properties")
|
||||
pro2 = collection_w2.describe().get("properties")
|
||||
assert pro["mmap.enabled"] == 'True'
|
||||
assert pro2["mmap.enabled"] == 'True'
|
||||
collection_w3.set_properties({'mmap.enabled': True})
|
||||
pro3 = collection_w3.describe().get("properties")
|
||||
assert pro3["mmap.enabled"] == 'True'
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_flush_collection_mmap(self):
|
||||
"""
|
||||
target: after flush, collection enables mmap
|
||||
method: after flush, collection enables mmap
|
||||
expected: the collection description message for mmap is normal
|
||||
"""
|
||||
self._connect()
|
||||
c_name = cf.gen_unique_str(prefix)
|
||||
collection_w, _ = self.collection_wrap.init_collection(c_name, schema=default_schema)
|
||||
collection_w.insert(cf.gen_default_list_data())
|
||||
collection_w.create_index(ct.default_float_vec_field_name, index_params=ct.default_flat_index,
|
||||
index_name=ct.default_index_name)
|
||||
collection_w.alter_index(ct.default_index_name, {'mmap.enabled': False})
|
||||
collection_w.flush()
|
||||
collection_w.set_properties({'mmap.enabled': True})
|
||||
pro = collection_w.describe().get("properties")
|
||||
assert pro["mmap.enabled"] == 'True'
|
||||
collection_w.alter_index(ct.default_index_name, {'mmap.enabled': True})
|
||||
collection_w.load()
|
||||
vectors = [[random.random() for _ in range(default_dim)] for _ in range(default_nq)]
|
||||
collection_w.search(vectors[:default_nq], default_search_field,
|
||||
default_search_params, default_limit,
|
||||
default_search_exp,
|
||||
check_task=CheckTasks.check_search_results,
|
||||
check_items={"nq": default_nq,
|
||||
"limit": default_limit})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_enable_mmap_after_drop_collection(self):
|
||||
"""
|
||||
target: enable mmap after deleting a collection
|
||||
method: enable mmap after deleting a collection
|
||||
expected: raise exception
|
||||
"""
|
||||
collection_w = self.init_collection_general(prefix, True, is_binary=True, is_index=False)[0]
|
||||
collection_w.drop()
|
||||
collection_w.set_properties({'mmap.enabled': True}, check_task=CheckTasks.err_res,
|
||||
check_items={ct.err_code: 100,
|
||||
ct.err_msg: f"collection not found"})
|
|
@ -1087,6 +1087,66 @@ class TestNewIndexBase(TestcaseBase):
|
|||
search_res, _ = collection_w.search(vectors, default_search_field, default_search_params, default_limit)
|
||||
assert len(search_res[0]) == ct.default_limit
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_turn_off_index_mmap(self):
|
||||
"""
|
||||
target: disabling and re-enabling mmap for index
|
||||
method: disabling and re-enabling mmap for index
|
||||
expected: search success
|
||||
"""
|
||||
self._connect()
|
||||
c_name = cf.gen_unique_str(prefix)
|
||||
collection_w, _ = self.collection_wrap.init_collection(c_name, schema=default_schema)
|
||||
collection_w.insert(cf.gen_default_list_data())
|
||||
collection_w.create_index(ct.default_float_vec_field_name, default_index_params, index_name=ct.default_index_name)
|
||||
collection_w.alter_index(ct.default_index_name, {'mmap.enabled': True})
|
||||
assert collection_w.index().params["mmap.enabled"] == 'True'
|
||||
collection_w.load()
|
||||
collection_w.release()
|
||||
collection_w.alter_index(ct.default_index_name, {'mmap.enabled': False})
|
||||
collection_w.load()
|
||||
assert collection_w.index().params["mmap.enabled"] == 'False'
|
||||
vectors = [[random.random() for _ in range(default_dim)] for _ in range(default_nq)]
|
||||
collection_w.search(vectors[:default_nq], default_search_field,
|
||||
default_search_params, default_limit,
|
||||
default_search_exp)
|
||||
collection_w.release()
|
||||
collection_w.alter_index(ct.default_index_name, {'mmap.enabled': True})
|
||||
assert collection_w.index().params["mmap.enabled"] == 'True'
|
||||
collection_w.load()
|
||||
collection_w.search(vectors[:default_nq], default_search_field,
|
||||
default_search_params, default_limit,
|
||||
default_search_exp,
|
||||
check_task=CheckTasks.check_search_results,
|
||||
check_items={"nq": default_nq,
|
||||
"limit": default_limit})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.parametrize("index, params", zip(ct.all_index_types[:6], ct.default_index_params[:6]))
|
||||
def test_drop_mmap_index(self, index, params):
|
||||
"""
|
||||
target: disabling and re-enabling mmap for index
|
||||
method: disabling and re-enabling mmap for index
|
||||
expected: search success
|
||||
"""
|
||||
self._connect()
|
||||
c_name = cf.gen_unique_str(prefix)
|
||||
collection_w, _ = self.collection_wrap.init_collection(c_name, schema=cf.gen_default_collection_schema())
|
||||
default_index = {"index_type": index, "params": params, "metric_type": "L2"}
|
||||
collection_w.create_index(field_name, default_index, index_name=f"mmap_index_{index}")
|
||||
collection_w.alter_index(f"mmap_index_{index}", {'mmap.enabled': True})
|
||||
assert collection_w.index().params["mmap.enabled"] == 'True'
|
||||
collection_w.drop_index(index_name=f"mmap_index_{index}")
|
||||
collection_w.create_index(field_name, default_index, index_name=f"index_{index}")
|
||||
collection_w.load()
|
||||
vectors = [[random.random() for _ in range(default_dim)] for _ in range(default_nq)]
|
||||
collection_w.search(vectors[:default_nq], default_search_field,
|
||||
default_search_params, default_limit,
|
||||
default_search_exp,
|
||||
check_task=CheckTasks.check_search_results,
|
||||
check_items={"nq": default_nq,
|
||||
"limit": default_limit})
|
||||
|
||||
|
||||
@pytest.mark.tags(CaseLabel.GPU)
|
||||
class TestNewIndexBinary(TestcaseBase):
|
||||
|
@ -1455,6 +1515,64 @@ class TestIndexInvalid(TestcaseBase):
|
|||
f"[{vector_name_list[0]} {vector_name_list[1]}], "
|
||||
f"please create index firstly"})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_set_non_exist_index_mmap(self):
|
||||
"""
|
||||
target: enabling mmap for non-existent indexes
|
||||
method: enabling mmap for non-existent indexes
|
||||
expected: raise exception
|
||||
"""
|
||||
c_name = cf.gen_unique_str(prefix)
|
||||
collection_w = self.init_collection_wrap(c_name, schema=default_schema)
|
||||
collection_w.insert(cf.gen_default_list_data())
|
||||
collection_w.create_index(ct.default_float_vec_field_name, index_params=ct.default_flat_index,
|
||||
index_name=ct.default_index_name)
|
||||
collection_w.alter_index("random_index_345", {'mmap.enabled': True},
|
||||
check_task=CheckTasks.err_res,
|
||||
check_items={ct.err_code: 65535,
|
||||
ct.err_msg: f"index not found"})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L1)
|
||||
def test_load_mmap_index(self):
|
||||
"""
|
||||
target: after loading, enable mmap for the index
|
||||
method: 1. data preparation and create index
|
||||
2. load collection
|
||||
3. enable mmap on index
|
||||
expected: raise exception
|
||||
"""
|
||||
c_name = cf.gen_unique_str(prefix)
|
||||
collection_w = self.init_collection_wrap(c_name, schema=default_schema)
|
||||
collection_w.insert(cf.gen_default_list_data())
|
||||
collection_w.create_index(ct.default_float_vec_field_name, index_params=ct.default_flat_index,
|
||||
index_name=ct.default_index_name)
|
||||
collection_w.load()
|
||||
collection_w.alter_index(binary_field_name, {'mmap.enabled': True},
|
||||
check_task=CheckTasks.err_res,
|
||||
check_items={ct.err_code: 104,
|
||||
ct.err_msg: f"can't alter index on loaded collection"})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_turning_on_mmap_for_scalar_index(self):
|
||||
"""
|
||||
target: turn on mmap for scalar indexes
|
||||
method: turn on mmap for scalar indexes
|
||||
expected: raise exception
|
||||
"""
|
||||
collection_w = self.init_collection_general(prefix, is_index=False, is_all_data_type=True)[0]
|
||||
scalar_index = ["Trie", "STL_SORT", "INVERTED"]
|
||||
scalar_fields = [ct.default_string_field_name, ct.default_int16_field_name, ct.default_int32_field_name]
|
||||
for i in range(len(scalar_fields)):
|
||||
index_name = f"scalar_index_name_{i}"
|
||||
scalar_index_params = {"index_type": f"{scalar_index[i]}"}
|
||||
collection_w.create_index(scalar_fields[i], index_params=scalar_index_params, index_name=index_name)
|
||||
assert collection_w.has_index(index_name=index_name)[0] is True
|
||||
collection_w.alter_index(index_name, {'mmap.enabled': True},
|
||||
check_task=CheckTasks.err_res,
|
||||
check_items={ct.err_code: 65535,
|
||||
ct.err_msg: f"index type {scalar_index[i]} does not support mmap"})
|
||||
collection_w.drop_index(index_name)
|
||||
|
||||
|
||||
@pytest.mark.tags(CaseLabel.GPU)
|
||||
class TestNewIndexAsync(TestcaseBase):
|
||||
|
@ -2023,6 +2141,26 @@ class TestIndexDiskann(TestcaseBase):
|
|||
check_items={ct.err_code: 1,
|
||||
ct.err_msg: "dim out of range: [8, 32768]"})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
def test_diskann_enable_mmap(self):
|
||||
"""
|
||||
target: enable mmap for unsupported indexes
|
||||
method: diskann index enable mmap
|
||||
expected: unsupported
|
||||
"""
|
||||
c_name = cf.gen_unique_str(prefix)
|
||||
collection_w = self.init_collection_wrap(c_name, schema=default_schema)
|
||||
collection_w.insert(cf.gen_default_list_data())
|
||||
collection_w.create_index(default_float_vec_field_name, ct.default_diskann_index, index_name=ct.default_index_name)
|
||||
collection_w.set_properties({'mmap.enabled': True})
|
||||
desc, _ = collection_w.describe()
|
||||
pro = desc.get("properties")
|
||||
assert pro["mmap.enabled"] == 'True'
|
||||
collection_w.alter_index(ct.default_index_name, {'mmap.enabled': True},
|
||||
check_task=CheckTasks.err_res,
|
||||
check_items={ct.err_code: 104,
|
||||
ct.err_msg: f"index type DISKANN does not support mmap"})
|
||||
|
||||
|
||||
@pytest.mark.tags(CaseLabel.GPU)
|
||||
class TestAutoIndex(TestcaseBase):
|
||||
|
|
|
@ -5061,6 +5061,66 @@ class TestSearchBase(TestcaseBase):
|
|||
"ids": insert_ids,
|
||||
"limit": top_k})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.parametrize("index, params", zip(ct.all_index_types[:6], ct.default_index_params[:6]))
|
||||
def test_each_index_with_mmap_enabled_search(self, index, params):
|
||||
"""
|
||||
target: test each index with mmap enabled search
|
||||
method: test each index with mmap enabled search
|
||||
expected: search success
|
||||
"""
|
||||
self._connect()
|
||||
c_name = cf.gen_unique_str(prefix)
|
||||
collection_w, _ = self.collection_wrap.init_collection(c_name, schema=cf.gen_default_collection_schema())
|
||||
default_index = {"index_type": index, "params": params, "metric_type": "L2"}
|
||||
collection_w.create_index(field_name, default_index, index_name="mmap_index")
|
||||
# mmap index
|
||||
collection_w.alter_index("mmap_index", {'mmap.enabled': True})
|
||||
# search
|
||||
collection_w.load()
|
||||
search_params = cf.gen_search_param(index)[0]
|
||||
vector = [[random.random() for _ in range(default_dim)] for _ in range(default_nq)]
|
||||
collection_w.search(vector, default_search_field, search_params, ct.default_limit)
|
||||
# enable mmap
|
||||
collection_w.release()
|
||||
collection_w.alter_index("mmap_index", {'mmap.enabled': False})
|
||||
collection_w.load()
|
||||
collection_w.search(vector, default_search_field, search_params, ct.default_limit,
|
||||
check_task=CheckTasks.check_search_results,
|
||||
check_items={"nq": default_nq,
|
||||
"limit": ct.default_limit})
|
||||
|
||||
@pytest.mark.tags(CaseLabel.L2)
|
||||
@pytest.mark.parametrize("index, params", zip(ct.all_index_types[7:9], ct.default_index_params[7:9]))
|
||||
def test_enable_mmap_search_for_binary_indexes(self, index, params, dim):
|
||||
"""
|
||||
target: enable mmap for binary indexes
|
||||
method: enable mmap for binary indexes
|
||||
expected: search success
|
||||
"""
|
||||
self._connect()
|
||||
c_name = cf.gen_unique_str(prefix)
|
||||
default_schema = cf.gen_default_binary_collection_schema(auto_id=False, dim=dim,
|
||||
primary_field=ct.default_int64_field_name)
|
||||
collection_w, _ = self.collection_wrap.init_collection(c_name, schema=default_schema)
|
||||
|
||||
default_index = {"index_type": index,
|
||||
"params": params, "metric_type": "JACCARD"}
|
||||
collection_w.create_index("binary_vector", default_index, index_name="binary_idx_name")
|
||||
collection_w.alter_index("binary_idx_name", {'mmap.enabled': True})
|
||||
collection_w.set_properties({'mmap.enabled': True})
|
||||
collection_w.load()
|
||||
pro = collection_w.describe().get("properties")
|
||||
assert pro["mmap.enabled"] == 'True'
|
||||
assert collection_w.index().params["mmap.enabled"] == 'True'
|
||||
# search
|
||||
binary_vectors = cf.gen_binary_vectors(3000, dim)[1]
|
||||
search_params = {"metric_type": "JACCARD", "params": {"nprobe": 10}}
|
||||
output_fields = [default_string_field_name]
|
||||
collection_w.search(binary_vectors[:default_nq], "binary_vector", search_params,
|
||||
default_limit, default_search_string_exp, output_fields=output_fields,
|
||||
check_task=CheckTasks.check_search_results)
|
||||
|
||||
|
||||
class TestSearchDSL(TestcaseBase):
|
||||
@pytest.mark.tags(CaseLabel.L0)
|
||||
|
|
Loading…
Reference in New Issue