浏览代码

Merge pull request #681 from LK4D4/speedup_etchosts_delete

Speedup etchosts delete
aboch 9 年之前
父节点
当前提交
9deda49cde
共有 2 个文件被更改,包括 81 次插入8 次删除
  1. 26 8
      libnetwork/etchosts/etchosts.go
  2. 55 0
      libnetwork/etchosts/etchosts_test.go

+ 26 - 8
libnetwork/etchosts/etchosts.go

@@ -1,6 +1,7 @@
 package etchosts
 package etchosts
 
 
 import (
 import (
+	"bufio"
 	"bytes"
 	"bytes"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
@@ -138,19 +139,36 @@ func Delete(path string, recs []Record) error {
 	if len(recs) == 0 {
 	if len(recs) == 0 {
 		return nil
 		return nil
 	}
 	}
-
-	old, err := ioutil.ReadFile(path)
+	old, err := os.Open(path)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	regexpStr := fmt.Sprintf("\\S*\\t%s\\n", regexp.QuoteMeta(recs[0].Hosts))
-	for _, r := range recs[1:] {
-		regexpStr = regexpStr + "|" + fmt.Sprintf("\\S*\\t%s\\n", regexp.QuoteMeta(r.Hosts))
+	var buf bytes.Buffer
+
+	s := bufio.NewScanner(old)
+	eol := []byte{'\n'}
+loop:
+	for s.Scan() {
+		b := s.Bytes()
+		if b[0] == '#' {
+			buf.Write(b)
+			buf.Write(eol)
+			continue
+		}
+		for _, r := range recs {
+			if bytes.HasSuffix(b, []byte("\t"+r.Hosts)) {
+				continue loop
+			}
+		}
+		buf.Write(b)
+		buf.Write(eol)
 	}
 	}
-
-	var re = regexp.MustCompile(regexpStr)
-	return ioutil.WriteFile(path, re.ReplaceAll(old, []byte("")), 0644)
+	old.Close()
+	if err := s.Err(); err != nil {
+		return err
+	}
+	return ioutil.WriteFile(path, buf.Bytes(), 0644)
 }
 }
 
 
 // Update all IP addresses where hostname matches.
 // Update all IP addresses where hostname matches.

+ 55 - 0
libnetwork/etchosts/etchosts_test.go

@@ -223,6 +223,10 @@ func TestDelete(t *testing.T) {
 			Hosts: "testhostname2",
 			Hosts: "testhostname2",
 			IP:    "2.2.2.2",
 			IP:    "2.2.2.2",
 		},
 		},
+		Record{
+			Hosts: "testhostname3",
+			IP:    "3.3.3.3",
+		},
 	}); err != nil {
 	}); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -232,6 +236,10 @@ func TestDelete(t *testing.T) {
 			Hosts: "testhostname1",
 			Hosts: "testhostname1",
 			IP:    "1.1.1.1",
 			IP:    "1.1.1.1",
 		},
 		},
+		Record{
+			Hosts: "testhostname3",
+			IP:    "3.3.3.3",
+		},
 	}); err != nil {
 	}); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
@@ -307,3 +315,50 @@ func TestConcurrentWrites(t *testing.T) {
 		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
 		t.Fatalf("Expected to find '%s' got '%s'", expected, content)
 	}
 	}
 }
 }
+
+func benchDelete(b *testing.B) {
+	b.StopTimer()
+	file, err := ioutil.TempFile("", "")
+	if err != nil {
+		b.Fatal(err)
+	}
+	defer func() {
+		b.StopTimer()
+		file.Close()
+		os.Remove(file.Name())
+		b.StartTimer()
+	}()
+
+	err = Build(file.Name(), "", "", "", nil)
+	if err != nil {
+		b.Fatal(err)
+	}
+
+	var records []Record
+	var toDelete []Record
+	for i := 0; i < 255; i++ {
+		record := Record{
+			Hosts: fmt.Sprintf("testhostname%d", i),
+			IP:    fmt.Sprintf("%d.%d.%d.%d", i, i, i, i),
+		}
+		records = append(records, record)
+		if i%2 == 0 {
+			toDelete = append(records, record)
+		}
+	}
+
+	if err := Add(file.Name(), records); err != nil {
+		b.Fatal(err)
+	}
+
+	b.StartTimer()
+	if err := Delete(file.Name(), toDelete); err != nil {
+		b.Fatal(err)
+	}
+}
+
+func BenchmarkDelete(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		benchDelete(b)
+	}
+}