- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在做一个项目,它应该从 JSON 文件中提取数据(包含有关波兰代表的信息),并仅使用这些数据进行一些计算。
代码执行正常,但有一种方法会大大降低一切速度。 我不是最擅长描述的,所以让我们展示一下我的 Jsonreader 类
Gist link
(第17、43、50行用的方法)代码看起来有点乱,但它工作正常,使用 jsonparser.parse 方法排除片段。每个特使花费大约 2 秒的时间是 Not Acceptable 。我必须更改那几行,但我不知道如何更改。我正在考虑将 json 文件指定为映射对象,然后对其进行处理,但我不确定这是否是一个好的选择。
(抱歉我的语法不好)
最佳答案
How can i check if problem lies in taht getContent method?
您可以间接地证明这一点:只需在您的网络浏览器网络调试器选项卡中检查您的服务 API 性能,或者测量简单 wget 的时间,例如 time wget YOUR_URL
。
我同意 Andreas怀疑 parse
方法是万恶之源。其实不然。如果您仔细查看要点,您会发现 parse
方法接受委托(delegate)读取器,该读取器实际上使用与远程主机“连接”的基础输入流。 I/O 通常是非常耗时的操作,尤其是网络。此外,建立 HTTP 连接在这里是一件昂贵的事情。在我的机器上,我得到了以下平均时间:
time wget URL
如果您使用 Unix 终端)。Andreas 建议的另一点是使用多线程以并行运行独立任务。不幸的是,这可以加快速度,但不会给您带来巨大的改变,因为您的服务访问速度不是那么快。
Executing SingleThreadedDemo...
Executing SingleThreadedDemo took 1063935ms = ~17:43
Executing MultiThreadedDemo...
Executing MultiThreadedDemo took 353044ms = ~5:53
稍后运行演示给出了以下结果(大约快了 3 倍,不知道之前减速的真正原因是什么)
Executing SingleThreadedDemo...
Executing SingleThreadedDemo took 382249ms = ~6:22
Executing MultiThreadedDemo...
Executing MultiThreadedDemo took 130502ms = ~2:11
Executing MultiThreadedDemo...
Executing MultiThreadedDemo took 110119ms = ~1:50
下面的类违反了一些良好的 OOP 设计理念,但为了不让类的总数膨胀,就让它的东西就在这里。
abstract class AbstractDemo
implements Callable<List<EnvoyData>> {
// Gson is thread-safe
private static final Gson gson = new Gson();
// JsonParser is thread-safe: https://groups.google.com/forum/#!topic/google-gson/u6hq2OVpszc
private static final JsonParser jsonParser = new JsonParser();
interface IPointsAndYearbooksConsumer {
void acceptPointsAndYearbooks(SerializedDataPoints points, SerializedDataYears yearbooks);
}
interface ITripsConsumer {
void acceptTrips(SerializedDataTrips trips);
}
AbstractDemo() {
}
protected abstract List<EnvoyData> doCall()
throws Exception;
// This implementation measures time (in milliseconds) taken for each demo call
@Override
public final List<EnvoyData> call()
throws Exception {
final String name = getClass().getSimpleName();
final long start = currentTimeMillis();
try {
out.printf("Executing %s...\n", name);
final List<EnvoyData> result = doCall();
out.printf("Executing %s took %dms\n", name, currentTimeMillis() - start);
return result;
} catch ( final Exception ex ) {
err.printf("Executing %s took %dms\n", name, currentTimeMillis() - start);
throw ex;
}
}
// This is a generic method that encapsulates generic pagination and lets you to iterate over the service pages in for-each style manner
static Iterable<JsonElement> jsonRequestsAt(final URL startUrl, final Function<? super JsonObject, URL> nextLinkExtrator, final JsonParser jsonParser) {
return () -> new Iterator<JsonElement>() {
private URL nextUrl = startUrl;
@Override
public boolean hasNext() {
return nextUrl != null;
}
@Override
public JsonElement next() {
if ( nextUrl == null ) {
throw new NoSuchElementException();
}
try ( final Reader reader = readFrom(nextUrl) ) {
final JsonElement root = jsonParser.parse(reader);
nextUrl = nextLinkExtrator.apply(root.getAsJsonObject());
return root;
} catch ( final IOException ex ) {
throw new RuntimeException(ex);
}
}
};
}
// Just a helper method to iterate over the start response
static Iterable<JsonElement> getAfterwords()
throws MalformedURLException {
return jsonRequestsAt(
afterwordsUrl(),
root -> {
try {
final JsonElement next = root.get("Links").getAsJsonObject().get("next");
return next != null ? new URL(next.getAsString()) : null;
} catch ( final MalformedURLException ex ) {
throw new RuntimeException(ex);
}
},
jsonParser
);
}
// Just extract points and yearbooks.
// You can return a custom data holder class, but this one uses consuming-style passing the results via its parameter consumer
static void extractPointsAndYearbooks(final Reader reader, final IPointsAndYearbooksConsumer consumer) {
final JsonObject expensesJsonObject = jsonParser.parse(reader)
.getAsJsonObject()
.get("layers")
.getAsJsonObject()
.get("wydatki")
.getAsJsonObject();
final SerializedDataPoints points = gson.fromJson(expensesJsonObject.get("punkty").getAsJsonArray(), SerializedDataPoints.class);
final SerializedDataYears yearbooks = gson.fromJson(expensesJsonObject.get("roczniki").getAsJsonArray(), SerializedDataYears.class);
consumer.acceptPointsAndYearbooks(points, yearbooks);
}
// The same as above but for another type of response
static void extractTrips(final Reader reader, final ITripsConsumer consumer) {
final JsonElement tripsJsonElement = jsonParser.parse(reader)
.getAsJsonObject()
.get("layers")
.getAsJsonObject()
.get("wyjazdy");
final SerializedDataTrips trips = tripsJsonElement.isJsonArray()
? gson.fromJson(tripsJsonElement.getAsJsonArray(), SerializedDataTrips.class)
: null;
consumer.acceptTrips(trips);
}
// It might be a constant field, but the next methods are dynamic (parameter-dependent), so let them all be similar
// Checked exceptions are not that evil, and let the call-site decide what to do with them
static URL afterwordsUrl()
throws MalformedURLException {
return new URL("https://api-v3.mojepanstwo.pl/dane/poslowie.json");
}
// The same as above
static URL afterwordsUrl(final int page)
throws MalformedURLException {
return new URL("https://api-v3.mojepanstwo.pl/dane/poslowie.json?_type=objects&page=" + page);
}
// The same as above
static URL tripsUrl(final int envoyId)
throws MalformedURLException {
return new URL("https://api-v3.mojepanstwo.pl/dane/poslowie/" + envoyId + ".json?layers[]=wyjazdy");
}
// The same as above
static URL expensesUrl(final int envoyId)
throws MalformedURLException {
return new URL("https://api-v3.mojepanstwo.pl/dane/poslowie/" + envoyId + ".json?layers[]=wydatki");
}
// Since jsonParser is encapsulated
static JsonElement parseJsonElement(final Reader reader) {
return jsonParser.parse(reader);
}
// A helper method to return a reader for the given URL
static Reader readFrom(final URL url)
throws IOException {
final HttpURLConnection request = (HttpURLConnection) url.openConnection();
request.connect();
return new BufferedReader(new InputStreamReader((InputStream) request.getContent()));
}
// Waits for all futures used in multi-threaded demo
// Not sure how good this method is since I'm not an expert in concurrent programming unfortunately
static void waitForAllFutures(final Iterable<? extends Future<?>> futures)
throws ExecutionException, InterruptedException {
final Iterator<? extends Future<?>> iterator = futures.iterator();
while ( iterator.hasNext() ) {
final Future<?> future = iterator.next();
future.get();
iterator.remove();
}
}
}
最简单的演示。整个数据拉取在单个线程中执行,因此它往往是这里最慢的演示。这是完全线程安全的,没有字段,可以声明为单例。
final class SingleThreadedDemo
extends AbstractDemo {
private static final Callable<List<EnvoyData>> singleThreadedDemo = new SingleThreadedDemo();
private SingleThreadedDemo() {
}
static Callable<List<EnvoyData>> getSingleThreadedDemo() {
return singleThreadedDemo;
}
@Override
protected List<EnvoyData> doCall()
throws IOException {
final List<EnvoyData> envoys = new ArrayList<>();
for ( final JsonElement afterwordJsonElement : getAfterwords() ) {
final JsonArray dataObjectArray = afterwordJsonElement.getAsJsonObject().get("Dataobject").getAsJsonArray();
for ( final JsonElement dataObjectElement : (Iterable<JsonElement>) dataObjectArray::iterator ) {
final int envoyId = dataObjectElement.getAsJsonObject().get("id").getAsInt();
try ( final Reader expensesReader = readFrom(expensesUrl(envoyId)) ) {
extractPointsAndYearbooks(expensesReader, (points, yearbooks) -> {
// ... consume points and yearbooks here
});
}
try ( final Reader tripsReader = readFrom(tripsUrl(envoyId)) ) {
extractTrips(tripsReader, trips -> {
// ... consume trips here
});
}
}
}
return envoys;
}
}
不幸的是,我在 Java 并发方面真的很弱,也许这些多线程演示可以得到显着改进。这个使用这两种方法的半多线程演示:
另请注意,此演示(以及下面的另一个多线程演示)不是故障安全的:如果在提交的任务中有任何东西抛出异常,则执行程序服务后台线程将不会正确终止。因此,您可能希望自己使其具有故障安全性和稳健性。
final class MultiThreadedDemo
extends AbstractDemo {
private final ExecutorService executorService;
private MultiThreadedDemo(final ExecutorService executorService) {
this.executorService = executorService;
}
static Callable<List<EnvoyData>> getMultiThreadedDemo(final ExecutorService executorService) {
return new MultiThreadedDemo(executorService);
}
@Override
protected List<EnvoyData> doCall()
throws InterruptedException, ExecutionException, MalformedURLException {
final List<EnvoyData> envoys = synchronizedList(new ArrayList<>());
final Collection<Future<?>> futures = new ConcurrentLinkedQueue<>();
for ( final JsonElement afterwordJsonElement : getAfterwords() ) {
final JsonArray dataObjectArray = afterwordJsonElement.getAsJsonObject().get("Dataobject").getAsJsonArray();
for ( final JsonElement dataObjectElement : (Iterable<JsonElement>) dataObjectArray::iterator ) {
final int envoyId = dataObjectElement.getAsJsonObject().get("id").getAsJsonPrimitive().getAsInt();
submitExtractPointsAndYearbooks(futures, envoyId);
submitExtractTrips(futures, envoyId);
}
}
waitForAllFutures(futures);
return envoys;
}
private void submitExtractPointsAndYearbooks(final Collection<? super Future<?>> futures, final int envoyId) {
futures.add(executorService.submit(() -> {
try ( final Reader expensesReader = readFrom(expensesUrl(envoyId)) ) {
extractPointsAndYearbooks(expensesReader, (points, yearbooks) -> {
// ... consume points and yearbooks here
});
return null;
}
}));
}
private void submitExtractTrips(final Collection<? super Future<?>> futures, final int envoyId) {
futures.add(executorService.submit(() -> {
try ( final Reader tripsReader = readFrom(tripsUrl(envoyId)) ) {
extractTrips(tripsReader, trips -> {
// ... consume trips here
});
return null;
}
}));
}
}
这个是上一个演示的增强版。但是这个演示提交了用于迭代服务页面的执行程序服务任务。为此,需要事先检测页数。并且拥有页面数量可以使 https://...poslowie.json?...page=...
URL 并行处理。请注意,如果找到超过 1 个页面,则下一次迭代从第 2 页开始,而不是重复请求。
final class MultiThreadedEstimatedPagesDemo
extends AbstractDemo {
private final ExecutorService executorService;
private MultiThreadedEstimatedPagesDemo(final ExecutorService executorService) {
this.executorService = executorService;
}
static Callable<List<EnvoyData>> getMultiThreadedEstimatedPagesDemo(final ExecutorService executorService) {
return new MultiThreadedEstimatedPagesDemo(executorService);
}
@Override
protected List<EnvoyData> doCall()
throws IOException, JsonIOException, JsonSyntaxException, InterruptedException, ExecutionException {
final List<EnvoyData> envoys = synchronizedList(new ArrayList<>());
final JsonObject page1RootJsonObject;
final int totalPages;
try ( final Reader page1Reader = readFrom(afterwordsUrl()) ) {
page1RootJsonObject = parseJsonElement(page1Reader).getAsJsonObject();
totalPages = estimateTotalPages(page1RootJsonObject);
}
final Collection<Future<?>> futures = new ConcurrentLinkedQueue<>();
futures.add(executorService.submit(() -> {
final JsonArray dataObjectArray = page1RootJsonObject.getAsJsonObject().get("Dataobject").getAsJsonArray();
for ( final JsonElement dataObjectElement : (Iterable<JsonElement>) dataObjectArray::iterator ) {
final int envoyId = dataObjectElement.getAsJsonObject().get("id").getAsInt();
submitExtractPointsAndYearbooks(futures, envoyId);
submitExtractTrips(futures, envoyId);
}
return null;
}));
for ( int page = 2; page <= totalPages; page++ ) {
final int finalPage = page;
futures.add(executorService.submit(() -> {
try ( final Reader reader = readFrom(afterwordsUrl(finalPage)) ) {
final JsonElement afterwordJsonElement = parseJsonElement(reader);
final JsonArray dataObjectArray = afterwordJsonElement.getAsJsonObject().get("Dataobject").getAsJsonArray();
for ( final JsonElement dataObjectElement : (Iterable<JsonElement>) dataObjectArray::iterator ) {
final int envoyId = dataObjectElement.getAsJsonObject().get("id").getAsInt();
submitExtractPointsAndYearbooks(futures, envoyId);
submitExtractTrips(futures, envoyId);
}
}
return null;
}));
}
waitForAllFutures(futures);
return envoys;
}
private static int estimateTotalPages(final JsonObject rootJsonObject) {
final int elementsPerPage = rootJsonObject.get("Dataobject").getAsJsonArray().size();
final int totalElements = rootJsonObject.get("Count").getAsInt();
return (int) ceil((double) totalElements / elementsPerPage);
}
private void submitExtractPointsAndYearbooks(final Collection<? super Future<?>> futures, final int envoyId) {
futures.add(executorService.submit(() -> {
try ( final Reader expensesReader = readFrom(expensesUrl(envoyId)) ) {
extractPointsAndYearbooks(expensesReader, (points, yearbooks) -> {
// ... consume points and yearbooks here
});
return null;
}
}));
}
private void submitExtractTrips(final Collection<? super Future<?>> futures, final int envoyId) {
futures.add(executorService.submit(() -> {
try ( final Reader tripsReader = readFrom(tripsUrl(envoyId)) ) {
extractTrips(tripsReader, trips -> {
// ... consume trips here
});
return null;
}
}));
}
}
以及演示本身:
public final class Test {
private Test() {
}
public static void main(final String... args)
throws Exception {
runSingleThreadedDemo();
runMultiThreadedDemo();
runMultiThreadedEstimatedPagesDemo();
}
private static void runSingleThreadedDemo()
throws Exception {
final Callable<?> singleThreadedDemo = getSingleThreadedDemo();
singleThreadedDemo.call();
}
private static void runMultiThreadedDemo()
throws Exception {
final ExecutorService executorService = newFixedThreadPool(getRuntime().availableProcessors());
final Callable<?> demo = getMultiThreadedDemo(executorService);
demo.call();
executorService.shutdown();
}
private static void runMultiThreadedEstimatedPagesDemo()
throws Exception {
final ExecutorService executorService = newFixedThreadPool(getRuntime().availableProcessors());
final Callable<?> demo = getMultiThreadedEstimatedPagesDemo(executorService);
demo.call();
executorService.shutdown();
}
}
关于java - JsonParser 的解析方法大大降低了我的代码速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41496526/
我在堆栈上创建了这段代码: function increase_brightness(hex, percent){ var r = parseInt(hex.substr(1, 2), 16)
为什么我能够LOWER COALESCE 中的每个项目,但无法LOWER整个COALESCE,否则我会遇到语法错误?例如: SELECT COALESCE(LOWER(google_provider_
我在谷歌上搜索到的所有内容都表明,以下任何一项都会将 double 舍入到小数点后两位。 double roundToFourDecimals(double d) { DecimalForma
我正在开发一个 flexdashboard/storyboard,我想在其中降低每个帧的高度。那可能吗? 示例代码: --- title: "Flex" output: flexdashboard
我在 WPF 中有一个图像控件。我需要减小图像尺寸控件的宽度和高度。但是当我这样做时,图像看起来不太好。数据丢失更多。 所以我想降低图像分辨率而不是仅仅改变图像控件的宽度和高度。 任何人都可以帮助我如
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题?通过 editing this post 添加详细信息并澄清问题. 1年前关闭。 Improve this
我正在扩展 Fluent NHibernate,以便更好地与 F# 一起使用(即引用支持),并希望获得一些关于降低 API 流畅性的反馈。 F# 要求使用返回值,除非它们是单位类型。所以这最终以“|>
我们有一个 BizTalk 2010 接收位置,它将获取一个 70MB 的文件,然后使用入站映射(在接收位置)和出站映射(在发送端口)生成一个 1GB 文件。 执行上述过程时,SQL Server 会
我的代码分析插件提示包含以下代码的方法中的代码复杂性。我注意到以下代码看起来可以组合,但我不知道如何做到这一点: for(Command command : commands) { if (c
我正在寻找一种方法来始终忽略 R 中 float 之间的微小差异(根据 IEC 60559,这些是 double 浮点),通过使用基本 R 工具而不诉诸 C 或 C++。换句话说,我想“四舍五入” d
在 Blazor 中使用 ChartJs.Blazor 的 BarChart 组件时是否可以降低甚至关闭动画速度?我发现这个 NuGet 包非常有用,但我不知道如何在更新条形图时关闭动画。为了更容易忽
所以我为一个游戏编写了这段代码,现在该游戏的速度非常快。我想降低 FPS,让游戏慢一点。 我认为我唯一的出路就是制作一个计时器。但我发现很难找到放置计时器的位置?谁能帮我解决这个问题吗? 所以我为一个
我正在编写一个程序,我担心它运行所需的时间和所占用的空间。 在程序中我使用了一个变量来存储数组的长度: int len=newarray3.length; 现在,我想知道是否能够通过不使用 len 变
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 2 年前。 Improve th
我用Java编写了一个程序,但它的计算时间很长,我不知道为什么。有人可以指点一下以降低复杂性吗?此外,在计算一些值(例如 3,100 之后)后,它会给出空指针异常。代码: public class F
我有下图,由 1 行 2 列的网格组成。我愿意 降低右侧子图的高度(3D PREDICTION),使棋盘平面看起来有点挤压并显示更好的视角。 在左侧子图的顶部添加一些边距(2D PREDICTION)
是否有一种简单的方法可以更改以 RGB 字符串形式给出的颜色的亮度? 例如 in_RGB = '#FF0000' --> out_RGB = '#CC0000' 最佳答案 将十六进制字符串转换为 R
我已经编写了代码来更改对象(不是进程)(在本例中是文件)的完整性级别。据我们所知,我们从中等完整性级别开始,但我想将其降低到“低”。我想运行完整性较低的 .txt 文件而不是默认介质。 我使用 WIN
是否可以在保持原始宽高不变的情况下降低图像分辨率? 我已经使用 BitmapFactoryOptions 尝试了几个选项: 在样本大小 inDensity、inScaled、inTargetDensi
是否有高级(Java)或低级方式(使用 native 代码)将 Android 设备上的蓝牙信号强度更改为最低? 目标是使设备在 20 厘米范围内可被发现?在 Internet 上根本找不到与此相关的
我是一名优秀的程序员,十分优秀!