2014-11-30 5 views
0

Я анализирую тройки FreeBase RDF, сжатые и потоковые с пакетом XML в Голанге. Тем не менее, я получаю ошибку из памяти.из памяти в golang при разборе Freebase RDF

Нужно ли мне собирать мусор? Как я могу это сделать? Как я могу очистить память после того, как я буду писать эту тройку в файл XML?

Вот мой код: http://play.golang.org/p/dWvbtcs7wy

пакет главный

import(
    "bufio" 
    "flag" 
    "fmt" 
    "io" 
    "net/url" 
    "os" 
    "regexp" 
    "strings" 
) 

var inputFile = flag.String("infile", "freebase-rdf", "Input file path") 
var filter, _ = regexp.Compile("^file:.*|^talk:.*|^special:.*|^wikipedia:.*|^wiktionary:.*|^user:.*|^user_talk:.*") 
type Redirect struct { 
    Title string `xml:"title,attr"` 
} 

type Page struct { 
    Title string `xml:"title"` 
    Abstract string `xml:""` 
} 

func CanonicaliseTitle(title string) string{ 
    can := strings.ToLower(title) 
    can = strings.Replace(can, " ", "_", -1) 
    can = url.QueryEscape(can) 
    return can 
} 

func convertFreebaseId(uri string) string{ 
    if strings.HasPrefix(uri, "<") && strings.HasSuffix(uri, ">") { 
     var id = uri[1 : len(uri)-1] 
     id = strings.Replace(id, "http://rdf.freebase.com/ns", "", -1) 
     id = strings.Replace(id, ".", "/", -1) 
     return id 
    } 
    return uri 
} 

func parseTriple(line string) (string, string, string){ 
    var parts = strings.Split(line, "\t") 
    subject := convertFreebaseId(parts[0]) 
    predicate := convertFreebaseId(parts[1]) 
    object := convertFreebaseId(parts[2]) 
    return subject, predicate, object 
} 

var (
    validRegexp = regexp.MustCompile("^[A-Za-z0-9][A-Za-z0-9_-]*$") 
    englishRegexp = regexp.MustCompile("@en") 
) 

func validTitle(content []string) bool{ 
    for _, v := range content{ 
     if !englishRegexp.MatchString(v) && len(v) > 1 && strings.Index(v, "[]") != -1{ 
     } 
    } 
    return true 
    } 

func validText(content []string) bool{ 
    for _, v := range content{ 
     if !validRegexp.MatchString(v) && len(v) > 1 && strings.Index(v, "[]") != -1{ 
      return false 
     } 
    } 
    return true 
} 

func processTopic(id string, properties map[string][]string, file io.Writer){ 
    if validTitle(properties["/type/object/name"]) && validText(properties["/common/document/text"]){ 
     fmt.Fprintf(file, "<card>\n") 
     fmt.Fprintf(file, "<title>\"%s\"</title>\n", properties["/type/object/name"]) 
     fmt.Fprintf(file, "<image>\"%s/%s\"</image>\n", "https://usercontent.googleapis.com/freebase/v1/image", id) 
     fmt.Fprintf(file, "<text>\"%s\"</text>\n", properties["/common/document/text"]) 
     fmt.Fprintf(file, "<facts>\n") 
     for k, v := range properties{ 
      for _, value := range v{ 
        fmt.Fprintf(file, "<fact property=\"%s\">%s</fact>\n", k, value) 
      } 
     } 
     fmt.Fprintf(file, "</facts>\n") 
     fmt.Fprintf(file, "</card>\n") 
    } 
} 

func main(){ 
    var current_mid = "" 
    current_topic := make(map[string][]string) 
    f, err := os.Open(*inputFile) 
    if err != nil { 
     fmt.Println(err) 
     return 
    } 
    r := bufio.NewReader(f) 
    xmlFile, _ := os.Create("freebase.xml") 
    line, err := r.ReadString('\n') 
    for err == nil{ 
     subject, predicate, object := parseTriple(line) 
     if subject == current_mid{ 
      current_topic[predicate] = append(current_topic[predicate], object) 
     }else if len(current_mid) > 0{ 
       processTopic(current_mid, current_topic, xmlFile) 
       current_topic = make(map[string][]string) 
     } 
     current_mid = subject 
     line, err = r.ReadString('\n') 
    } 
    processTopic(current_mid, current_topic, xmlFile) 
    if err != io.EOF { 
     fmt.Println(err) 
     return 
    } 
} 
+1

Вы проверяли размер своей карты, когда предикат не уникален? Потому что единственное, что я могу придумать, это то, что когда предикат уже существует, он продолжает добавлять к нему объект. Это может означать, что запись становится очень большой. – Dippo

+0

Просто бросать кучу кода у нас недостаточно. Нам нужна воспроизводимая ошибка. [Как создать минимальный, полный и проверенный пример.] (Http://stackoverflow.com/help/mcve) – peterSO

ответ

1

Я не уверен, что это ваша проблема, хотя читать ваш код, кажется, вы ничего не протекает, - но вы можете настроить Поведение GC немного с SetGCPercent()http://golang.org/pkg/runtime/debug/#SetGCPercent

Согласно TFM, a collection is triggered when the ratio of freshly allocated data to live data remaining after the previous collection reaches this percentage.. Ставка по умолчанию - 100%, что означает для программ, которые делают много небольших распределений и содержат много ОЗУ, накладные расходы могут быть огромными. У меня HTTP-кеш занимал более 200% размера кэша один раз. Попробуйте настроить процент примерно на 10% и посмотреть, помогает ли он.