首先,我看到了一个现有问题(JCIFS: file retrieval is too slow to be usable),但它是针对Java而不是Android,并且没有一个建议的答案有效。
我在Android Studio 2.3中为Android SDK 25(7.1.1)创建了一个默认项目,将库与compile 'jcifs:jcifs:1.3.17'
相关联,并键入以下简单的测试代码。结果低于代码。
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
jcifs.Config.setProperty("jcifs.util.loglevel", "3");
//jcifs.Config.setProperty("jcifs.smb.client.dfs.disabled", "false");
//jcifs.Config.setProperty("jcifs.resolveOrder", "DNS");
try
{
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("", ID, PASSWORD);
final SmbFile smb = new SmbFile("smb://192.168.XX.XX/Share/FileName", auth);
Thread t = new Thread(new Runnable()
{
@Override
public void run()
{
Log.d(TAG, "Test Start");
for(int i = 1000; i<10000; i+=1000)
measure(i);
Log.d(TAG, "Test End");
}
private void measure(int bufferSize)
{
Log.d(TAG, "=====Buffer: " + bufferSize + "============");
try
{
byte[] buffer = new byte[bufferSize];
int read = 0;
InputStream str = smb.getInputStream();
long start = System.nanoTime();
while(read < 1000000)
read += str.read(buffer);
long end = System.nanoTime();
str.close();
float time = (float) ((end - start) / 1000000000d);
float speed = (float) read / 1048576 / time;
Log.d(TAG, "Time:" + time + ", size =" + read);
Log.d(TAG, "Speed = " + speed + "MB/s");
}
catch(IOException exc)
{
exc.printStackTrace();
}
}
});
t.start();
}
catch(Exception exc)
{
Log.d(TAG, exc.toString());
}
}
结果
Test Start
=====Buffer: 1000============
Time:2.210785, size =1000000
Speed = 0.43137363MB/s
=====Buffer: 2000============
Time:1.4158936, size =1000000
Speed = 0.6735495MB/s
=====Buffer: 3000============
Time:1.0556641, size =1002000
Speed = 0.9051948MB/s
=====Buffer: 4000============
Time:0.7543335, size =1000000
Speed = 1.2642609MB/s
=====Buffer: 5000============
Time:3.6557617, size =1000000
Speed = 0.26086885MB/s
=====Buffer: 6000============
Time:3.292389, size =1002000
Speed = 0.2902396MB/s
=====Buffer: 7000============
Time:2.9179688, size =1001000
Speed = 0.32715496MB/s
=====Buffer: 8000============
Time:2.462616, size =1000000
Speed = 0.38726068MB/s
=====Buffer: 9000============
Time:3.9379272, size =1008000
Speed = 0.24411413MB/s
Test End
读取速度约为0.2MB / s~1.2MB / s。该设备连接到150Mbps的Wi-Fi,理论上它可以达到10MB / s以上。 SMB服务器也不慢。当我将文件复制到笔记本电脑时,读取速度大约为30MB / s。
为什么这么慢?我该怎么检查?如果缓冲区大小为4000,为什么读取速度大约高5倍(1.2MB / s)
顺便说一句,我已经测试过与其他商业应用程序复制相同的文件。文件指挥官,华硕文件管理器显示相似的低速,ES文件资源管理器显示约2MB / s,Solid Explorer显示约5MB / s。由于我很确定所有这些都使用JCIFS(虽然它的版本可能略有不同),但必须有一种方法可以像Solid Explorer一样达到至少5MB / s的速度。
答案 0 :(得分:2)
在Windows计算机上使用WireShark(网络分析工具)后,我发现无论我设置哪种缓冲区大小,读取SMB命令总是为Windows计算机提供4286字节。似乎SmbFileInputStream.java
正在使用服务器的最大缓冲区大小。
但是当我看到来自Soild Explorer的数据包时,它是32768字节。所以,我反编译了Solid Explorer的APK(它当然是混淆的),并在其中看到了SmbFileInputStream.java
文件(该文件属于JCIFS)。似乎Solid Explorer的开发人员修改了该文件,并设置了更大的readSize
。所以,我尝试了类似的事情。然后我使用相同的代码达到了5MB / s。
由于JCIFS附带了LGPL,因此Solid Explorer使用修改后的JCIFS而不泄露源代码这一事实违反了JCIFS&#39;执照。但是,哦,好吧,似乎很多Android应用程序开发人员都忽略了他们使用的库的许可证。他们甚至没有恰当地相信他们使用的开源库。
答案 1 :(得分:0)
您是否尝试过:require = {
baseUrl: '/assets/js',
paths: {
'intl-tel-input': '/assets/vendor/intl-tel-input/build/js/intlTelInput.min',
},
shim: {
'intl-tel-input': {
deps: ['libphonenumber-utils']
},
}
};
就我而言(虽然是Java),它对慢速连接很有帮助。默认情况下为jcifs.Config.setProperty("jcifs.smb.client.dfs.disabled", "true");
对我来说唯一的问题是,我不确定该财产是否会破坏&#34;其他工作正常的事情......
答案 2 :(得分:0)
有一个大缓冲区大小读取的补丁:
从自述文件内部:
这个补丁增加了两个可以改善读写的SMB 表现相当。不幸的是,它并不是很清楚 所有实现都正确支持命令。请注意 除了这个补丁'和'需要添加0xFFFF' SmbTransport.java:doRecv:~437显示为:
int size = Encdec.dec_uint16be(BUF,2)&amp; 0xFFFF的;
尽管已在1.2.7中进行了此更改。
不确定这是否适用于Android,但解决方案可能类似。