mzsanford / cld

Language Detection based on Chromium's Compact Language Detector library
http://mzsanford.com/blog/introducing-libcld
BSD 3-Clause "New" or "Revised" License
104 stars 24 forks source link

/ports/node *.detectSync() fails too often / returns different results than *.detect() #25

Open Abromeit opened 10 years ago

Abromeit commented 10 years ago

To be honest, I don't use .detectSync() at the moment, because i don't understand the parameter skipWeakMatches in detail. But it's elegant (requires us like 1 line of code) and darn fast (50% faster than .detect() in some cases). So it might be cool to invest a little more devtime into this function.

During my tests i noted that .detectSync() behaves completely different than .detect(), i.e. it fails a lot more often. Looks like this isn't a problem with specialchars or sth., but most likely with the string length.

The following table compares the output of

------- | --- | --- | --- 80 | de | de | de 160 | de | de | de 240 | de | de | de 320 | de | de | de 400 | de | false | de 480 | de | false | de 560 | de | false | de 640 | de | false | de 720 | de | de | de 800 | de | false | de 880 | de | false | de 960 | de | false | de 1040 | de | false | de 1120 | de | false | de 1200 | de | false | de 1280 | de | false | de 1360 | de | false | de 1440 | de | de | de 1520 | de | de | de 1600 | de | de | de 1680 | de | de | de 1760 | de | de | de 1840 | de | de | de 1920 | de | de | de 2000 | de | de | de 2080 | de | de | de 2160 | de | de | de 2240 | de | de | de 2320 | de | de | de 2400 | de | de | de 2480 | de | de | de 2560 | de | de | de 2640 | de | de | de 2720 | de | de | de 2800 | de | de | de 2880 | de | de | de 2960 | de | de | de 3040 | de | de | de

Aaaand some hacky code:

var ASYNC = require('async');
var LANGDETECT = new (require('languagedetect'))('iso2');
var CLD = new (require('cld/cld.node').LanguageDetector)();

//str_repeat('Foo',3) => 'FooFooFoo'
function str_repeat(a,b){ for(var c="";;)if(b&1&&(c+=a),b>>=1)a+=a;else break;return c }

//LANGDETECT.detect()
function detect_v1(str,cb)
{ 
  var res = LANGDETECT.detect(str,1); 

  cb(
    null, 
    res.length && res[0][0] ? res[0][0] : false
  ); 
}

//CLD.detectSync()
function detect_v2(str,cb)
{ 
  var res = CLD.detectSync(str);

  cb(
    null, 
    res && res !== 'un' ? res : false
  ); 
}

//CLD.detect()
function detect_v3(str,cb)
{ 
  CLD.detect(str,function(res)
  { 
    cb(
      null, 
      res && res.languageCode && res.languageCode !== 'un' ? res.languageCode : false
    ); 
  }); 
}

console.log('#Chars  | V1  | V2  | V3 ');   
console.log('------- | --- | --- | ---');   
for(var i=1, i_max=100, str; i <= i_max; ++i)
{
  //str = str_repeat('Hans und Gretel gingen in den Wald, dort war es finster und auch so bitterkalt. ',i);
    str = str_repeat('Alle meine Entchen schwimmen auf dem See, den Kopf dann in das Wasser und blub. ',i);

  (function(str)
  {
    ASYNC.parallel(
    {
      v1: function(cb){ detect_v1(str,cb); },
      v2: function(cb){ detect_v2(str,cb); },
      v3: function(cb){ detect_v3(str,cb); }
    },
    function(err,res)
    {
      console.log(str.length+' | '+res.v1+' | '+res.v2+' | '+res.v3);
    });  
  })(str);
}
mzsanford commented 10 years ago

I paired to test code down to just sync/async and I don't see the same issue in my build:

$ node async_test.js
#Chars  | V1  | V2
------- | --- | ---
80 | de | de
160 | de | de
240 | de | de
320 | de | de
400 | de | de
480 | de | de
560 | de | de
640 | de | de
720 | de | de
800 | de | de
880 | de | de
960 | de | de
1040 | de | de
1120 | de | de
1200 | de | de
1280 | de | de
1360 | de | de
1440 | de | de
1520 | de | de
1600 | de | de
1680 | de | de
1760 | de | de
1840 | de | de
1920 | de | de
2000 | de | de
2080 | de | de
2160 | de | de
2240 | de | de
2320 | de | de
2400 | de | de
2480 | de | de
2560 | de | de
2640 | de | de
2720 | de | de
2800 | de | de
2880 | de | de
2960 | de | de
3040 | de | de
3120 | de | de
3200 | de | de
3280 | de | de
3360 | de | de
3440 | de | de
3520 | de | de
3600 | de | de
3680 | de | de
3760 | de | de
3840 | de | de
3920 | de | de
4000 | de | de
4080 | de | de
4160 | de | de
4240 | de | de
4320 | de | de
4400 | de | de
4480 | de | de
4560 | de | de
4640 | de | de
4720 | de | de
4800 | de | de
4880 | de | de
4960 | de | de
5040 | de | de
5120 | de | de
5200 | de | de
5280 | de | de
5360 | de | de
5440 | de | de
5520 | de | de
5600 | de | de
5680 | de | de
5760 | de | de
5840 | de | de
5920 | de | de
6000 | de | de
6080 | de | de
6160 | de | de
6240 | de | de
6320 | de | de
6400 | de | de
6480 | de | de
6560 | de | de
6640 | de | de
6720 | de | de
6800 | de | de
6880 | de | de
6960 | de | de
7040 | de | de
7120 | de | de
7200 | de | de
7280 | de | de
7360 | de | de
7440 | de | de
7520 | de | de
7600 | de | de
7680 | de | de
7760 | de | de
7840 | de | de
7920 | de | de
8000 | de | de

What OS are you running on? Let me know and I'll try to setup a VM and replicate the issue.

Abromeit commented 10 years ago

Ok, maybe it's more about memory or sth. Here's the same test but with a fixed string length. Results are the same for every script-execution.

#Chars V1 V2 V3
8000 de de de
8000 de false de
8000 de false de
8000 de false de
8000 de false de
8000 de de de
8000 de de de
8000 de de de
8000 de de de
8000 de de de
8000 de de de
8000 de de de
8000 de de de
8000 de de de
//
// ...
//
console.log('#Chars  | V1  | V2  | V3 ');   
console.log('------- | --- | --- | ---');   

var str = str_repeat('Alle meine Entchen schwimmen auf dem See, den Kopf dann in das Wasser und blub. ',100);

for(var i=1, i_max=100; i <= i_max; ++i)
{
  ASYNC.parallel(
  {
    v1: function(cb){ detect_v1(str,cb); },
    v2: function(cb){ detect_v2(str,cb); },
    v3: function(cb){ detect_v3(str,cb); }
  },
  function(err,res)
  {
    console.log(str.length+' | '+res.v1+' | '+res.v2+' | '+res.v3);
  });  
}

Debian 3.2.0-2-686-pae and should be a weird squeeze version after all.