Liferay 并发文件条目上传
Liferay Concurrent FileEntry Upload
问题陈述:
在 liferay 中,我必须将一个 zip 文件导入到 liferay cms 中的某个文件夹中,到目前为止,我已经实现了 zip 文件的串行解压缩,创建它的文件夹,然后创建它的文件。这里的问题是整个过程需要很多时间。所以我不得不在创建文件夹和创建文件时使用并行方法。
我的解决方案:
我用 java java.util.concurrent.ExecutorService 创建了 Executors.newFixedThreadPool(NTHREDS)其中 NTHREDS 是 运行 并行的线程数(比如 5)
- 我从 zip 中读取了所有文件夹路径并放置了 zip 列表
entires (files) 针对文件夹路径作为 HashMap 中的键
- 遍历地图中的所有键并顺序创建文件夹
- 现在遍历map中的zip条目(文件)列表并传递给线程工作者,每个工作者一个文件,然后将这些工作者发送到
要执行的 ExecutorService
到目前为止,我没有发现整个过程的时间有任何显着减少,我的方向是否正确? liferay是否支持并发添加文件?我究竟做错了什么?
我将非常感谢在这方面的任何帮助
下面是我的代码
imports
...
...
public class TestImportZip {
private static final int NTHREDS = 5;
ExecutorService executor = null;
...
...
....
Map<String,Folder> folders = new HashMap<String,Folder>();
File zipsFile = null;
public TestImportZip(............,File zipFile, .){
.
.
this.zipsFile = zipFile;
this.executor = Executors.newFixedThreadPool(NTHREDS);
}
// From here the process starts
public void importZip() {
Map<String,List<ZipEntry>> foldersMap = new HashMap<String, List<ZipEntry>>();
try (ZipFile zipFile = new ZipFile(zipsFile)) {
zipFile.stream().forEach(entry -> {
String entryName = entry.getName();
if(entryName.contains("/")) {
String key = entryName.substring(0, entryName.lastIndexOf("/"));
List<ZipEntry> zipEntries = foldersMap.get(key);
if(zipEntries == null){
zipEntries = new ArrayList<>();
}
zipEntries.add(entry);
foldersMap.put(key,zipEntries);
}
});
createFolders(foldersMap.keySet());
createFiles(foldersMap);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void createFolders(Set<String> folderPathSets) {
// create folder and put the folder in map
.
.
.
folders.put(folderPath,folder);
}
private void createFiles(Map<String, List<ZipEntry>> foldersMap) {
.
.
.
//Traverse all the files from all the list in map and send them to worker
createFileWorker(folderPath,zipEntry);
}
private void createFileWorker(String folderPath,ZipEntry zipEntry) {
CreateEntriesWorker cfw = new CreateEntriesWorker(folderPath, zipEntry);
executor.execute(cfw);
}
class CreateEntriesWorker implements Runnable{
Folder folder = null;
ZipEntry entryToCreate = null;
public CreateEntriesWorker(String folderPath, ZipEntry zipEntry){
this.entryToCreate = zipEntry;
// get folder from already created folder map
this.folder = folders.get(folderPath);
}
public void run() {
if(this.folder != null) {
long startTime = System.currentTimeMillis();
try (ZipFile zipFile = new ZipFile(zipsFile)) {
InputStream inputStream = zipFile.getInputStream(entryToCreate);
try{
String name = entryToCreate.getName();
// created file entry here
}catch(Exception e){
}finally{
if(inputStream != null)
inputStream.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
您的简化代码不包含任何我认识的 Liferay 参考。您提供的描述暗示您正在尝试优化某些代码,但不会从您的尝试中获得更好的性能。这通常表明您正在尝试优化问题的错误方面(或者它已经非常优化)。
您需要确定操作的实际瓶颈,以便了解优化是否可行。俗话说"premature optimization is the root of all evil"。这是什么意思?
我将在这里完全编造数字 - 不要引用我的话:它们是出于说明目的随意发明的。比方说,您将 Zip 文件的内容添加到 Liferay 存储库的操作分配给以下百分比的操作资源:
- 4% 压缩文件 decoding/decompressing
- 6% 文件 I/O 用于 zip 操作和临时文件
- 10% 数据库操作用于存储文件
- 60% 用于从 word、pdf、excel 和其他存储在 zip 文件中的文件中提取纯文本,以便在全文索引中索引文档
- 用于整理索引的全文索引库的 20% 开销。
假设您正在优化 zip 文件 decoding/decompressing - 您期望数字的总体改进是什么?
虽然我的数字是编造的:如果您的优化没有任何结果,我建议将它们反转,测量您需要优化的地方并继续那个地方(或者接受它并升级您的硬件,如果那地方遥不可及)。
运行 CPU、I/O、内存和其他潜在瓶颈的那些数字。确定您的实际瓶颈#1,修复它,再次测量。您会看到瓶颈 #2 得到了提升。重复冲洗直到您满意为止
问题陈述:
在 liferay 中,我必须将一个 zip 文件导入到 liferay cms 中的某个文件夹中,到目前为止,我已经实现了 zip 文件的串行解压缩,创建它的文件夹,然后创建它的文件。这里的问题是整个过程需要很多时间。所以我不得不在创建文件夹和创建文件时使用并行方法。
我的解决方案:
我用 java java.util.concurrent.ExecutorService 创建了 Executors.newFixedThreadPool(NTHREDS)其中 NTHREDS 是 运行 并行的线程数(比如 5)
- 我从 zip 中读取了所有文件夹路径并放置了 zip 列表 entires (files) 针对文件夹路径作为 HashMap 中的键
- 遍历地图中的所有键并顺序创建文件夹
- 现在遍历map中的zip条目(文件)列表并传递给线程工作者,每个工作者一个文件,然后将这些工作者发送到 要执行的 ExecutorService
到目前为止,我没有发现整个过程的时间有任何显着减少,我的方向是否正确? liferay是否支持并发添加文件?我究竟做错了什么?
我将非常感谢在这方面的任何帮助
下面是我的代码
imports
...
...
public class TestImportZip {
private static final int NTHREDS = 5;
ExecutorService executor = null;
...
...
....
Map<String,Folder> folders = new HashMap<String,Folder>();
File zipsFile = null;
public TestImportZip(............,File zipFile, .){
.
.
this.zipsFile = zipFile;
this.executor = Executors.newFixedThreadPool(NTHREDS);
}
// From here the process starts
public void importZip() {
Map<String,List<ZipEntry>> foldersMap = new HashMap<String, List<ZipEntry>>();
try (ZipFile zipFile = new ZipFile(zipsFile)) {
zipFile.stream().forEach(entry -> {
String entryName = entry.getName();
if(entryName.contains("/")) {
String key = entryName.substring(0, entryName.lastIndexOf("/"));
List<ZipEntry> zipEntries = foldersMap.get(key);
if(zipEntries == null){
zipEntries = new ArrayList<>();
}
zipEntries.add(entry);
foldersMap.put(key,zipEntries);
}
});
createFolders(foldersMap.keySet());
createFiles(foldersMap);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void createFolders(Set<String> folderPathSets) {
// create folder and put the folder in map
.
.
.
folders.put(folderPath,folder);
}
private void createFiles(Map<String, List<ZipEntry>> foldersMap) {
.
.
.
//Traverse all the files from all the list in map and send them to worker
createFileWorker(folderPath,zipEntry);
}
private void createFileWorker(String folderPath,ZipEntry zipEntry) {
CreateEntriesWorker cfw = new CreateEntriesWorker(folderPath, zipEntry);
executor.execute(cfw);
}
class CreateEntriesWorker implements Runnable{
Folder folder = null;
ZipEntry entryToCreate = null;
public CreateEntriesWorker(String folderPath, ZipEntry zipEntry){
this.entryToCreate = zipEntry;
// get folder from already created folder map
this.folder = folders.get(folderPath);
}
public void run() {
if(this.folder != null) {
long startTime = System.currentTimeMillis();
try (ZipFile zipFile = new ZipFile(zipsFile)) {
InputStream inputStream = zipFile.getInputStream(entryToCreate);
try{
String name = entryToCreate.getName();
// created file entry here
}catch(Exception e){
}finally{
if(inputStream != null)
inputStream.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
您的简化代码不包含任何我认识的 Liferay 参考。您提供的描述暗示您正在尝试优化某些代码,但不会从您的尝试中获得更好的性能。这通常表明您正在尝试优化问题的错误方面(或者它已经非常优化)。
您需要确定操作的实际瓶颈,以便了解优化是否可行。俗话说"premature optimization is the root of all evil"。这是什么意思?
我将在这里完全编造数字 - 不要引用我的话:它们是出于说明目的随意发明的。比方说,您将 Zip 文件的内容添加到 Liferay 存储库的操作分配给以下百分比的操作资源:
- 4% 压缩文件 decoding/decompressing
- 6% 文件 I/O 用于 zip 操作和临时文件
- 10% 数据库操作用于存储文件
- 60% 用于从 word、pdf、excel 和其他存储在 zip 文件中的文件中提取纯文本,以便在全文索引中索引文档
- 用于整理索引的全文索引库的 20% 开销。
假设您正在优化 zip 文件 decoding/decompressing - 您期望数字的总体改进是什么?
虽然我的数字是编造的:如果您的优化没有任何结果,我建议将它们反转,测量您需要优化的地方并继续那个地方(或者接受它并升级您的硬件,如果那地方遥不可及)。
运行 CPU、I/O、内存和其他潜在瓶颈的那些数字。确定您的实际瓶颈#1,修复它,再次测量。您会看到瓶颈 #2 得到了提升。重复冲洗直到您满意为止