mirror of
https://github.com/ollama/ollama.git
synced 2026-04-30 16:08:07 -05:00
server: fix slow 'ollama rm' of models with many layers (#13680)
RemoveLayers was calling Manifests() for each layer to check if it was shared with other models. For models with many blobs (e.g., tensor models), this caused O(N*M) manifest reads. Now loads manifests once and builds a set of in-use digests.
This commit is contained in:
@@ -47,16 +47,40 @@ func (m *Manifest) Remove() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manifest) RemoveLayers() error {
|
func (m *Manifest) RemoveLayers() error {
|
||||||
for _, layer := range append(m.Layers, m.Config) {
|
ms, err := Manifests(true)
|
||||||
if layer.Digest != "" {
|
if err != nil {
|
||||||
if err := layer.Remove(); errors.Is(err, os.ErrNotExist) {
|
return err
|
||||||
slog.Debug("layer does not exist", "digest", layer.Digest)
|
}
|
||||||
} else if err != nil {
|
|
||||||
return err
|
// Build set of digests still in use by other manifests
|
||||||
|
inUse := make(map[string]struct{})
|
||||||
|
for _, other := range ms {
|
||||||
|
for _, layer := range append(other.Layers, other.Config) {
|
||||||
|
if layer.Digest != "" {
|
||||||
|
inUse[layer.Digest] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove layers not used by any other manifest
|
||||||
|
for _, layer := range append(m.Layers, m.Config) {
|
||||||
|
if layer.Digest == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, used := inUse[layer.Digest]; used {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
blob, err := GetBlobsPath(layer.Digest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := os.Remove(blob); errors.Is(err, os.ErrNotExist) {
|
||||||
|
slog.Debug("layer does not exist", "digest", layer.Digest)
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user